diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..bcd4ec632e0f046e00341e3cc24442c88a288fcf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,35 +1,6 @@ -*.7z filter=lfs diff=lfs merge=lfs -text -*.arrow filter=lfs diff=lfs merge=lfs -text -*.bin filter=lfs diff=lfs merge=lfs -text -*.bz2 filter=lfs diff=lfs merge=lfs -text -*.ckpt filter=lfs diff=lfs merge=lfs -text -*.ftz filter=lfs diff=lfs merge=lfs -text -*.gz filter=lfs diff=lfs merge=lfs -text -*.h5 filter=lfs diff=lfs merge=lfs -text -*.joblib filter=lfs diff=lfs merge=lfs -text -*.lfs.* filter=lfs diff=lfs merge=lfs -text -*.mlmodel filter=lfs diff=lfs merge=lfs -text -*.model filter=lfs diff=lfs merge=lfs -text -*.msgpack filter=lfs diff=lfs merge=lfs -text -*.npy filter=lfs diff=lfs merge=lfs -text -*.npz filter=lfs diff=lfs merge=lfs -text -*.onnx filter=lfs diff=lfs merge=lfs -text -*.ot filter=lfs diff=lfs merge=lfs -text -*.parquet filter=lfs diff=lfs merge=lfs -text -*.pb filter=lfs diff=lfs merge=lfs -text -*.pickle filter=lfs diff=lfs merge=lfs -text -*.pkl filter=lfs diff=lfs merge=lfs -text -*.pt filter=lfs diff=lfs merge=lfs -text -*.pth filter=lfs diff=lfs merge=lfs -text -*.rar filter=lfs diff=lfs merge=lfs -text -*.safetensors filter=lfs diff=lfs merge=lfs -text -saved_model/**/* filter=lfs diff=lfs merge=lfs -text -*.tar.* filter=lfs diff=lfs merge=lfs -text -*.tar filter=lfs diff=lfs merge=lfs -text -*.tflite filter=lfs diff=lfs merge=lfs -text -*.tgz filter=lfs diff=lfs merge=lfs -text -*.wasm filter=lfs diff=lfs merge=lfs -text -*.xz filter=lfs diff=lfs merge=lfs -text -*.zip filter=lfs diff=lfs merge=lfs -text -*.zst filter=lfs diff=lfs merge=lfs -text -*tfevents* filter=lfs diff=lfs merge=lfs -text +# Keep language stats focused on the public Python package. +*.ipynb linguist-vendored +*.html linguist-generated +exp/** linguist-vendored +evaluations/** linguist-vendored +docs/** linguist-documentation diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4c07a33badde15bc35c1ddb814ef70bc4989e2a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +# Python-generated files +__pycache__/ +*.py[oc] +build/ +dist/ +wheels/ +*.egg-info + +# Virtual environments +.venv + +# Local data +data/ + +# dev +AGENTS.md +readme_dev.md +.superpowers/ +contribute/ruler/ +repos/.DS_Store +repomix-output.xml + +# FlashTrace generated artifacts +trace.json +trace.html +*.trace.json +*.trace.html +exp/**/output/ +exp/**/out/ +exp/**/out-*/ +*.npz +.DS_Store +repomix-output.xml diff --git a/.python-version b/.python-version new file mode 100644 index 0000000000000000000000000000000000000000..24ee5b1be9961e38a503c8e764b7385dbb6ba124 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000000000000000000000000000000000..976f4d26bf88a8815c617b9be6e881826d17b2d0 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Faithfulness Eval", + "type": "debugpy", + "request": "launch", + "module": "evaluations.faithfulness", + "args": [ + "--model", + "qwen-4B", + "--cuda_num", + "1", + "--num_examples", + "500", + "--attr_func", + "IG", + "--dataset", + "facts" + ], + "console": "integratedTerminal", + "justMyCode": true + } + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..a3010395fb64d73ce27e11f8e3ee29c342b36fa9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Wenbo Pan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000000000000000000000000000000000000..6b9d312c712031dc20c0a105e41e10ace080a18c --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,5 @@ +include README.md +include LICENSE +include pyproject.toml +include examples/*.py +include tests/*.py diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ef296043586d8725108df58cfe06ab980a0f217b --- /dev/null +++ b/README.md @@ -0,0 +1,293 @@ +

+ FlashTrace logo +

+ +

FlashTrace

+ +

+ Fast token attribution for reasoning language models. +

+ +

+ PyPI + Python + License + PyTorch + arXiv +

+ +FlashTrace traces generated answers back to the prompt tokens that shaped them. Use it from Python or the command line, export JSON traces, and render standalone HTML heatmaps for inspection and sharing. + +

+ ๐Ÿ“„ Paper +  ยท  + ๐Ÿš€ Quickstart +  ยท  + ๐Ÿ’ป CLI +  ยท  + ๐Ÿ“ Citation +

+ +## Why FlashTrace + +Reasoning models produce long generated chains, final answers, and intermediate spans that deserve targeted inspection. FlashTrace gives researchers a package-first workflow for tracing a selected generated span back to its supporting prompt tokens. + +You get: + +- top-k prompt tokens ranked by attribution score +- JSON traces for downstream analysis +- standalone HTML token heatmaps +- optional per-hop attribution panels +- inclusive generation-token span controls for answer and reasoning segments + +## Install + +From PyPI: + +```bash +pip install flashtrace +``` + +From a local checkout: + +```bash +pip install -e . +``` + +For development: + +```bash +pip install -e ".[dev]" +``` + +FlashTrace uses PyTorch, Transformers, Accelerate, NumPy, and tqdm. A CUDA-capable GPU is recommended for public-scale Hugging Face models. + +## Quickstart + +```python +from flashtrace import FlashTrace, load_model_and_tokenizer + +prompt = """Context: Paris is the capital of France. +Question: What is the capital of France?""" +target = "Paris" + +model, tokenizer = load_model_and_tokenizer("Qwen/Qwen3-8B", device_map="auto") +tracer = FlashTrace(model, tokenizer, chunk_tokens=128, sink_chunk_tokens=32) + +trace = tracer.trace( + prompt=prompt, + target=target, + output_span=(0, 0), + hops=1, +) + +print(trace.topk_inputs(10)) +trace.to_json("trace.json") +trace.to_html("trace.html") +``` + +`trace.topk_inputs(10)` returns `TokenScore` objects aligned to prompt-token indices: + +```text +rank index token score +1 2 Paris 0.184 +2 7 capital 0.131 +3 10 France 0.119 +``` + +`trace.html` is a standalone heatmap that highlights prompt tokens by final attribution score and includes trace metadata for the selected generated span. + +`FlashTrace(..., use_chat_template=True)` formats prompts with the tokenizer chat template for chat-tuned models. + +## Command Line + +Create prompt and target files: + +```bash +printf "Context: Paris is the capital of France.\nQuestion: What is the capital of France?\n" > prompt.txt +printf "Paris" > target.txt +``` + +Run a trace: + +```bash +flashtrace trace \ + --model Qwen/Qwen3-8B \ + --prompt prompt.txt \ + --target target.txt \ + --output-span 0:0 \ + --hops 1 \ + --html trace.html \ + --json trace.json +``` + +The command prints a compact top-k table and writes the requested artifacts. + +Useful flags: + +- `--model`: Hugging Face model id or local model path +- `--prompt`: UTF-8 prompt text file +- `--target`: UTF-8 target text file +- `--output-span`: inclusive `START:END` indices over generated tokens +- `--reasoning-span`: inclusive `START:END` indices for a reasoning segment +- `--method`: `flashtrace`, `ifr-span`, or `ifr-matrix` +- `--recompute-attention`: lower-memory attention recomputation path +- `--use-chat-template`: format prompts with the tokenizer chat template +- `--device-map`: Transformers device map, default `auto` +- `--dtype`: `auto`, `float16`, `bfloat16`, or `float32` + +## Token Spans + +`output_span` and `reasoning_span` use inclusive generation-token indices. The first generated token has index `0`. + +Use an initial trace to inspect tokenization: + +```python +for index, token in enumerate(trace.generation_tokens): + print(index, repr(token)) +``` + +Then choose spans: + +```python +trace = tracer.trace( + prompt=prompt, + target=target, + reasoning_span=(0, 79), + output_span=(80, 85), + hops=1, +) +``` + +Scores are aligned to `trace.prompt_tokens`. `trace.per_hop_scores` stores the same prompt-token alignment for each hop. + +## Interpreting Results + +High-scoring prompt tokens are the tokens FlashTrace attributes most strongly to the selected generated span. For answer inspection, use `output_span` around the final answer tokens. For chain-of-thought or reasoning inspection, use `reasoning_span` around the generated reasoning segment. + +Recommended workflow: + +1. Run a trace with your prompt and target. +2. Inspect `trace.generation_tokens`. +3. Select the answer or reasoning span. +4. Export `trace.html`. +5. Compare top-k tokens with the source prompt and any expected evidence. + +## Supported Models + +FlashTrace targets Llama/Qwen-style decoder-only Hugging Face causal LMs with: + +- `model.layers` +- Q/K/V/O attention projections +- RMSNorm or LayerNorm +- RoPE metadata + +Validated model families for the first public release: + +- Qwen2 +- Qwen3 +- Llama + +## Python API + +The public package exports: + +```python +from flashtrace import FlashTrace, TraceResult, load_model_and_tokenizer +``` + +`FlashTrace.trace(...)` accepts: + +- `prompt: str` +- `target: str | None` +- `output_span: tuple[int, int] | None` +- `reasoning_span: tuple[int, int] | None` +- `hops: int` +- `method: "flashtrace" | "ifr-span" | "ifr-matrix"` +- `renorm_threshold: float | None` + +`TraceResult` includes: + +- `prompt_tokens` +- `generation_tokens` +- `scores` +- `per_hop_scores` +- `thinking_ratios` +- `output_span` +- `reasoning_span` +- `method` +- `metadata` + +Export helpers: + +```python +trace.topk_inputs(20) +trace.to_dict() +trace.to_json("trace.json") +trace.to_html("trace.html") +``` + +## Examples + +```bash +python examples/quickstart.py --help +python examples/quickstart.py \ + --model Qwen/Qwen3-8B \ + --prompt "Context: Paris is the capital of France. Question: What is the capital of France?" \ + --target "Paris" \ + --output-span 0:0 \ + --html trace.html +``` + +Heavy model examples are intended for GPU environments. CPU smoke tests use tiny randomly initialized models. + +## Repository Map + +- `flashtrace/`: reusable Python package +- `examples/`: public quickstarts +- `tests/`: CPU smoke tests +- `exp/`: paper experiments and research artifacts +- `docs/superpowers/`: design and implementation planning documents + +## Research Experiments + +The `exp/` directory contains the paper-era experiment runners, case studies, and saved artifacts. The public package API lives in `flashtrace/`; experiment scripts keep compatibility imports during the package migration. + +## Troubleshooting + +**CUDA memory** + +Use smaller models, lower precision, `device_map="auto"`, shorter prompts, or `--recompute-attention`. + +**Span selection** + +Print `trace.generation_tokens` and select inclusive generated-token indices. Tokenization can split visible words into multiple model tokens. + +**Deterministic generation** + +Pass a `target` file for attribution against a known output. Leave `--target` out when you want the CLI to generate with deterministic defaults. + +**Tokenizer alignment** + +Inspect `trace.prompt_tokens` and `trace.generation_tokens` when scores appear shifted from visible text. Attribution scores follow tokenizer-level alignment. + +**HTML export** + +`trace.to_html("trace.html")` writes a standalone file that can be opened locally or shared as an artifact. + +## Paper + +FlashTrace implements the method described in [Towards Long-Horizon Interpretability: Efficient and Faithful Multi-Token Attribution for Reasoning LLMs](https://arxiv.org/abs/2602.01914). + +## Citation + +```bibtex +@misc{pan2026flashtrace, + title={Towards Long-Horizon Interpretability: Efficient and Faithful Multi-Token Attribution for Reasoning LLMs}, + author={Pan, Wenbo and Liu, Zhichao and Wang, Xianlong and Yu, Haining and Jia, Xiaohua}, + year={2026}, + eprint={2602.01914}, + archivePrefix={arXiv}, + primaryClass={cs.LG} +} +``` diff --git a/attribution_datasets.py b/attribution_datasets.py new file mode 100644 index 0000000000000000000000000000000000000000..b4bfd4dd7feceac710e1462c60bcf91c8af6194f --- /dev/null +++ b/attribution_datasets.py @@ -0,0 +1,265 @@ +from __future__ import annotations + +import json +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any, Dict, Iterable, Iterator, List, Optional, Sequence + +# Import sentence splitter from shared utils; fallback when unavailable +try: + from shared_utils import create_sentences, create_sentences_fallback, nlp +except Exception: + from shared_utils import create_sentences_fallback as create_sentences + nlp = None + + +@dataclass +class AttributionExample: + prompt: str + target: Optional[str] = None + indices_to_explain: Optional[List[int]] = None + attr_mask_indices: Optional[List[int]] = None + metadata: Dict[str, Any] = field(default_factory=dict) + + +class AttributionDataset(Iterable[AttributionExample]): + """Base iterable for attribution-ready datasets.""" + + name: str = "dataset" + + def __init__(self) -> None: + self.examples: List[AttributionExample] = [] + + def __iter__(self) -> Iterator[AttributionExample]: + return iter(self.examples) + + def __len__(self) -> int: # pragma: no cover - trivial + return len(self.examples) + + def __getitem__(self, item): # pragma: no cover - convenience + return self.examples[item] + + +def _add_dummy_facts_to_prompt(text_sentences: Sequence[str]) -> List[str]: + """ + Reproduces the original behaviour of interleaving dummy sentences with the + provided text segments so attribution heads can be masked easily. + """ + result: List[str] = [] + for sentence in text_sentences: + result.append(sentence) + result.append(" Unrelated Sentence.") + return result + + +class MathAttributionDataset(AttributionDataset): + """Dataset wrapper for synthetic math problems with dummy context facts.""" + + name = "math" + + def __init__(self, path: str | Path, tokenizer: Any) -> None: + super().__init__() + data_path = Path(path) + with data_path.open("r", encoding="utf-8") as f: + raw_examples = json.load(f) + + for entry in raw_examples: + question_text = entry["question"] + sentences = create_sentences(question_text, tokenizer) + if not sentences: + continue + + context_sentences = sentences[:-1] + question_sentence = sentences[-1] + if question_sentence.startswith(" "): + question_sentence = question_sentence[1:] + + context_with_dummy = _add_dummy_facts_to_prompt(context_sentences) + question_with_dummy = _add_dummy_facts_to_prompt([question_sentence]) + + prompt = "".join(context_with_dummy) + "\n" + "".join(question_with_dummy) + total_sentences = len(context_with_dummy) + len(question_with_dummy) + attr_mask_indices = list(range(0, total_sentences, 2)) + + self.examples.append( + AttributionExample( + prompt=prompt, + target=None, + indices_to_explain=[-2], + attr_mask_indices=attr_mask_indices, + metadata={"raw_question": question_text}, + ) + ) + + +class FactsAttributionDataset(AttributionDataset): + """Dataset wrapper for curated factual prompts with explicit gold attributions.""" + + name = "facts" + + def __init__(self, path: str | Path) -> None: + super().__init__() + data_path = Path(path) + with data_path.open("r", encoding="utf-8") as f: + raw_examples = json.load(f) + + for entry in raw_examples: + metadata = { + key: value + for key, value in entry.items() + if key not in {"prompt", "target", "indices_to_explain", "attr_mask_indices"} + } + self.examples.append( + AttributionExample( + prompt=entry["prompt"], + target=entry.get("target"), + indices_to_explain=entry.get("indices_to_explain"), + attr_mask_indices=entry.get("attr_mask_indices"), + metadata=metadata, + ) + ) + + +class MoreHopQAAttributionDataset(AttributionDataset): + """Dataset wrapper for multi-hop QA prompts without explicit gold attribution.""" + + name = "morehopqa" + + def __init__(self, path: str | Path) -> None: + super().__init__() + data_path = Path(path) + with data_path.open("r", encoding="utf-8") as f: + raw_examples = json.load(f) + + for entry in raw_examples: + context_chunks = ["".join(item[1]) for item in entry.get("context", [])] + context = " ".join(context_chunks) + prompt = context + "\n" + entry["question"] + + self.examples.append( + AttributionExample( + prompt=prompt, + target=None, + indices_to_explain=[-2], + attr_mask_indices=None, + metadata={ + "answer": entry.get("answer"), + "id": entry.get("_id"), + "original_context": entry.get("context"), + }, + ) + ) + + +# added +class RulerAttributionDataset(AttributionDataset): + """Dataset wrapper for raw RULER JSONL files with needle spans. + + Expects a JSONL file produced by repos/RULER (with added `needle_spans`). + Each line must contain at least: `input`, `answer_prefix`, `outputs`, and + optionally `needle_spans` with character spans relative to `input`. + + Mapping logic: + - prompt = input + answer_prefix + - target = answer_prefix (+ optional space) + ", ".join(outputs) + - sentence indices computed over " " + prompt (leading space to match evaluator) + - each span is shifted by +1 to account for that leading space + - attr_mask_indices = union of all sentences covered by any span + - indices_to_explain = [0] when target is present + """ + + name = "ruler" + + def __init__(self, path: str | Path) -> None: + super().__init__() + data_path = Path(path) + if not data_path.exists(): + raise FileNotFoundError(f"RULER file not found: {data_path}") + + # Use shared nlp pipeline; fallback to a naive splitter if unavailable + if nlp is not None: + def _sentence_bounds(text: str) -> List[tuple[int, int]]: + doc = nlp(text) + return [(s.start_char, s.end_char) for s in doc.sents] + else: + def _sentence_bounds(text: str) -> List[tuple[int, int]]: + # Naive fallback: split on newlines, produce contiguous ranges + bounds: List[tuple[int, int]] = [] + start = 0 + parts = text.split("\n") + for idx, part in enumerate(parts): + end = start + len(part) + if end > start: + bounds.append((start, end)) + start = end + 1 + if not bounds: + bounds = [(0, len(text))] + return bounds + + def _map_spans(bounds: Sequence[tuple[int, int]], spans: Sequence[tuple[int, int]]) -> List[int]: + indices: set[int] = set() + for start, end in spans: + matched = False + for i, (bs, be) in enumerate(bounds): + if start >= bs and end <= be: + indices.add(i) + matched = True + break + if not matched: + # fallback: include all sentences with any overlap + for i, (bs, be) in enumerate(bounds): + if not (end <= bs or start >= be): + indices.add(i) + return sorted(indices) + + def _read_jsonl(fp: Path) -> Iterator[Dict[str, Any]]: + with fp.open("r", encoding="utf-8") as f: + for line in f: + line = line.strip() + if line: + yield json.loads(line) + + for entry in _read_jsonl(data_path): + input_text: str = entry.get("input", "") + answer_prefix: str = entry.get("answer_prefix", "") + outputs = entry.get("outputs", []) or [] + + # Build prompt/target + prompt = input_text + answer_prefix + if outputs: + sep = " " if answer_prefix and not answer_prefix.endswith((" ", "\n", "\t")) else "" + target = answer_prefix + sep + ", ".join(outputs) + else: + target = answer_prefix + + # Sentence bounds over leading-space prompt to match evaluator + prompt_for_seg = " " + prompt + bounds = _sentence_bounds(prompt_for_seg) + + # Collect spans and shift by +1 for the leading space + spans_raw = [] + for item in entry.get("needle_spans", []) or []: + span = item.get("span") + if isinstance(span, list) and len(span) == 2: + spans_raw.append((int(span[0]) + 1, int(span[1]) + 1)) + + attr_indices = _map_spans(bounds, spans_raw) if spans_raw else None + + self.examples.append( + AttributionExample( + prompt=prompt, + target=target or None, + indices_to_explain=[0] if target else None, + attr_mask_indices=attr_indices, + metadata={ + "dataset": "ruler", + "length": entry.get("length"), + "length_w_model_temp": entry.get("length_w_model_temp"), + "outputs": outputs, + "answer_prefix": answer_prefix, + "token_position_answer": entry.get("token_position_answer"), + "needle_spans": entry.get("needle_spans"), + "prompt_sentence_count": len(bounds), + }, + ) + ) diff --git a/docs/superpowers/plans/2026-05-03-flashtrace-public-package.md b/docs/superpowers/plans/2026-05-03-flashtrace-public-package.md new file mode 100644 index 0000000000000000000000000000000000000000..8e9dbdcd5abaa7597c332c044c07a4d3c1836c60 --- /dev/null +++ b/docs/superpowers/plans/2026-05-03-flashtrace-public-package.md @@ -0,0 +1,1605 @@ +# FlashTrace Public Package Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Build an installable `flashtrace` package with a stable Python API, CLI tracing command, JSON export, HTML heatmap export, README quickstart, and CPU smoke tests. + +**Architecture:** Create a package-first structure while preserving temporary root compatibility wrappers for existing experiment scripts. Move the IFR implementation and attribution engines into `flashtrace/`, wrap them with `FlashTrace` and `TraceResult`, then expose a CLI and public examples. + +**Tech Stack:** Python 3.10+, PyTorch, Transformers, Accelerate, NumPy, tqdm, argparse, pytest. + +--- + +## File Structure + +Create or modify these files: + +- Create: `flashtrace/__init__.py` for public exports. +- Create: `flashtrace/core.py` from `ifr_core.py`. +- Create: `flashtrace/shared_utils.py` from `shared_utils.py`. +- Create: `flashtrace/lrp_rules.py` from `lrp_rules.py`. +- Create: `flashtrace/lrp_patches.py` from `lrp_patches.py`. +- Create: `flashtrace/attribution.py` from `llm_attr.py`. +- Create: `flashtrace/improved.py` from `ft_ifr_improve.py`. +- Create: `flashtrace/result.py` for `TokenScore` and `TraceResult`. +- Create: `flashtrace/viz.py` for standalone HTML token heatmaps. +- Create: `flashtrace/tracer.py` for the `FlashTrace` facade. +- Create: `flashtrace/model_io.py` for Hugging Face loading helpers. +- Create: `flashtrace/cli.py` for `flashtrace trace`. +- Create: `flashtrace/baselines/__init__.py`. +- Create: `flashtrace/baselines/attnlrp.py`. +- Modify: `ifr_core.py`, `shared_utils.py`, `lrp_rules.py`, `lrp_patches.py`, `llm_attr.py`, `ft_ifr_improve.py` into root compatibility wrappers. +- Modify: `pyproject.toml` package metadata and console script. +- Modify: `.gitignore` generated artifact rules. +- Create: `README.md`. +- Create: `LICENSE`. +- Create: `examples/quickstart.py`. +- Create: `tests/helpers.py`. +- Create: `tests/test_imports.py`. +- Create: `tests/test_core_recompute.py`. +- Create: `tests/test_result.py`. +- Create: `tests/test_tracer.py`. +- Create: `tests/test_cli.py`. +- Delete: `model_generation.py`. + +## Task 1: Package Metadata And Skeleton + +**Files:** +- Modify: `pyproject.toml` +- Create: `flashtrace/__init__.py` +- Create: `flashtrace/tracer.py` +- Create: `flashtrace/result.py` +- Create: `flashtrace/model_io.py` +- Create: `flashtrace/cli.py` +- Create: `flashtrace/baselines/__init__.py` +- Create: `flashtrace/baselines/attnlrp.py` +- Test: `tests/test_imports.py` + +- [ ] **Step 1: Write the failing public import test** + +Create `tests/test_imports.py`: + +```python +def test_public_imports(): + import flashtrace + + assert flashtrace.FlashTrace.__name__ == "FlashTrace" + assert flashtrace.TraceResult.__name__ == "TraceResult" + assert callable(flashtrace.load_model_and_tokenizer) +``` + +- [ ] **Step 2: Run the import test and see the expected failure** + +Run: + +```bash +uv run pytest tests/test_imports.py -q +``` + +Expected: pytest reports an import failure for `flashtrace`. + +- [ ] **Step 3: Create package directories** + +Run: + +```bash +mkdir -p flashtrace/baselines tests +``` + +- [ ] **Step 4: Add minimal public package files** + +Create `flashtrace/tracer.py`: + +```python +class FlashTrace: + """Public facade for FlashTrace attribution.""" + + def __init__(self, model, tokenizer, **kwargs): + self.model = model + self.tokenizer = tokenizer + self.options = dict(kwargs) +``` + +Create `flashtrace/result.py`: + +```python +from __future__ import annotations + +from dataclasses import dataclass + + +@dataclass(frozen=True) +class TraceResult: + """Public attribution result returned by FlashTrace.""" + + prompt_tokens: list[str] + generation_tokens: list[str] + scores: list[float] +``` + +Create `flashtrace/model_io.py`: + +```python +def load_model_and_tokenizer(*args, **kwargs): + """Load a Hugging Face causal LM and tokenizer.""" + + raise RuntimeError("load_model_and_tokenizer will be implemented in the model IO task.") +``` + +Create `flashtrace/cli.py`: + +```python +def main(argv=None): + """FlashTrace command-line entrypoint.""" + + raise RuntimeError("CLI will be implemented in the CLI task.") +``` + +Create `flashtrace/baselines/__init__.py`: + +```python +"""Baseline attribution methods for FlashTrace.""" +``` + +Create `flashtrace/baselines/attnlrp.py`: + +```python +"""AttnLRP baseline exports.""" +``` + +Create `flashtrace/__init__.py`: + +```python +"""FlashTrace: efficient multi-token attribution for reasoning LLMs.""" + +from .model_io import load_model_and_tokenizer +from .result import TraceResult +from .tracer import FlashTrace + +__all__ = ["FlashTrace", "TraceResult", "load_model_and_tokenizer"] +``` + +- [ ] **Step 5: Update package metadata** + +Replace `pyproject.toml` with: + +```toml +[project] +name = "flashtrace" +version = "0.1.0" +description = "Efficient multi-token attribution for reasoning language models." +readme = "README.md" +requires-python = ">=3.10" +dependencies = [ + "accelerate>=1.11.0", + "matplotlib>=3.6", + "networkx>=3.3", + "numpy>=2.0", + "seaborn>=0.11", + "spacy>=3.8", + "torch>=2.5", + "tqdm>=4.67", + "transformers>=4.53", + "wordfreq>=3.1.1", +] + +[project.optional-dependencies] +baselines = [ + "bert-score>=0.3.13", + "evaluate>=0.4.6", + "sentence-transformers>=4.1.0", +] +eval = [ + "datasets>=2.21", + "evaluate>=0.4.6", +] +dev = [ + "pytest>=8.0", +] + +[project.scripts] +flashtrace = "flashtrace.cli:main" + +[tool.setuptools.packages.find] +include = ["flashtrace*"] +``` + +- [ ] **Step 6: Run the import test** + +Run: + +```bash +uv run pytest tests/test_imports.py -q +``` + +Expected: `1 passed`. + +- [ ] **Step 7: Commit** + +Run: + +```bash +git add pyproject.toml flashtrace tests/test_imports.py +git commit -m "feat: add flashtrace package skeleton" +``` + +## Task 2: Core IFR Migration + +**Files:** +- Create: `flashtrace/core.py` +- Create: `flashtrace/shared_utils.py` +- Modify: `ifr_core.py` +- Modify: `shared_utils.py` +- Create: `tests/helpers.py` +- Create: `tests/test_core_recompute.py` + +- [ ] **Step 1: Add the tiny-model test helper** + +Create `tests/helpers.py`: + +```python +from __future__ import annotations + +from tokenizers import Tokenizer, models, pre_tokenizers +from transformers import AutoConfig, AutoModelForCausalLM, PreTrainedTokenizerFast + + +def make_tiny_qwen2_model_and_tokenizer( + *, + n_layers: int = 3, + d_model: int = 48, + n_heads: int = 4, + n_kv_heads: int = 2, + max_pos: int = 128, +): + config = AutoConfig.for_model( + "qwen2", + vocab_size=500, + hidden_size=d_model, + intermediate_size=d_model * 2, + num_hidden_layers=n_layers, + num_attention_heads=n_heads, + num_key_value_heads=n_kv_heads, + max_position_embeddings=max_pos, + use_sliding_window=False, + attn_implementation="eager", + ) + model = AutoModelForCausalLM.from_config(config, attn_implementation="eager") + model.eval() + + backend = Tokenizer(models.WordLevel(vocab={f"t{i}": i for i in range(500)}, unk_token="t0")) + backend.pre_tokenizer = pre_tokenizers.Whitespace() + tokenizer = PreTrainedTokenizerFast(tokenizer_object=backend, eos_token="t1", pad_token="t2") + tokenizer.chat_template = "{% for m in messages %}{{ m['content'] }}{% endfor %}" + return model, tokenizer +``` + +- [ ] **Step 2: Write the failing core import smoke test** + +Create `tests/test_core_recompute.py`: + +```python +import torch + +from flashtrace import core +from tests.helpers import make_tiny_qwen2_model_and_tokenizer + + +def test_core_metadata_and_weight_pack(): + model, _ = make_tiny_qwen2_model_and_tokenizer() + + metadata = core.extract_model_metadata(model) + weight_pack = core.build_weight_pack(metadata, next(model.parameters()).dtype) + + assert metadata.n_layers == 3 + assert metadata.n_heads_q == 4 + assert metadata.n_kv_heads == 2 + assert len(weight_pack) == 3 + assert torch.is_tensor(weight_pack[0]["v_w"]) +``` + +- [ ] **Step 3: Run the core smoke test and see the expected failure** + +Run: + +```bash +uv run pytest tests/test_core_recompute.py::test_core_metadata_and_weight_pack -q +``` + +Expected: pytest reports missing `flashtrace.core`. + +- [ ] **Step 4: Copy the IFR core into the package** + +Run: + +```bash +cp ifr_core.py flashtrace/core.py +``` + +- [ ] **Step 5: Copy shared utilities into the package** + +Run: + +```bash +cp shared_utils.py flashtrace/shared_utils.py +``` + +- [ ] **Step 6: Replace root `ifr_core.py` with a compatibility wrapper** + +Replace `ifr_core.py` with: + +```python +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.core import * # noqa: F401,F403 +``` + +- [ ] **Step 7: Replace root `shared_utils.py` with a compatibility wrapper** + +Replace `shared_utils.py` with: + +```python +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.shared_utils import * # noqa: F401,F403 +``` + +- [ ] **Step 8: Run the core smoke test** + +Run: + +```bash +uv run pytest tests/test_core_recompute.py::test_core_metadata_and_weight_pack -q +``` + +Expected: `1 passed`. + +- [ ] **Step 9: Commit** + +Run: + +```bash +git add flashtrace/core.py flashtrace/shared_utils.py ifr_core.py shared_utils.py tests/helpers.py tests/test_core_recompute.py +git commit -m "feat: move IFR core into package" +``` + +## Task 3: Attribution Engine Migration + +**Files:** +- Create: `flashtrace/lrp_rules.py` +- Create: `flashtrace/lrp_patches.py` +- Create: `flashtrace/attribution.py` +- Create: `flashtrace/improved.py` +- Modify: `lrp_rules.py` +- Modify: `lrp_patches.py` +- Modify: `llm_attr.py` +- Modify: `ft_ifr_improve.py` +- Modify: `flashtrace/baselines/attnlrp.py` +- Test: `tests/test_core_recompute.py` + +- [ ] **Step 1: Extend the recompute test with package attribution paths** + +Append to `tests/test_core_recompute.py`: + +```python +from flashtrace.attribution import LLMIFRAttribution + + +def test_package_attribution_recompute_matches_stored_attention(): + model, tokenizer = make_tiny_qwen2_model_and_tokenizer(n_layers=2, d_model=32, n_heads=4, n_kv_heads=2) + prompt = "t10 t20 t30 t40" + target = "t60 t70" + + stored = LLMIFRAttribution(model, tokenizer, recompute_attention=False).calculate_ifr_span(prompt, target) + recomputed = LLMIFRAttribution(model, tokenizer, recompute_attention=True).calculate_ifr_span(prompt, target) + + diff = (stored.attribution_matrix - recomputed.attribution_matrix).abs().max().item() + assert diff < 1e-5 +``` + +- [ ] **Step 2: Run the package attribution test and see the expected failure** + +Run: + +```bash +uv run pytest tests/test_core_recompute.py::test_package_attribution_recompute_matches_stored_attention -q +``` + +Expected: pytest reports missing `flashtrace.attribution`. + +- [ ] **Step 3: Copy LRP helpers and attribution engines into the package** + +Run: + +```bash +cp lrp_rules.py flashtrace/lrp_rules.py +cp lrp_patches.py flashtrace/lrp_patches.py +cp llm_attr.py flashtrace/attribution.py +cp ft_ifr_improve.py flashtrace/improved.py +``` + +- [ ] **Step 4: Update imports in `flashtrace/attribution.py`** + +Edit package-local imports to this form: + +```python +from .core import ( + IFRParameters, + ModelMetadata, + attach_hooks, + build_weight_pack, + compute_ifr_for_all_positions, + compute_ifr_sentence_aggregate, + compute_multi_hop_ifr, + extract_model_metadata, +) +from .shared_utils import ( + DEFAULT_GENERATE_KWARGS, + DEFAULT_PROMPT_TEMPLATE, + create_sentences, + create_sentence_masks, +) +from .lrp_patches import lrp_context, detect_model_type +``` + +- [ ] **Step 5: Update imports in `flashtrace/lrp_patches.py`** + +Edit the LRP helper import to: + +```python +from .lrp_rules import stop_gradient, divide_gradient, identity_rule_implicit +``` + +- [ ] **Step 6: Update imports in `flashtrace/improved.py`** + +Edit the top-level package imports to: + +```python +from . import attribution as llm_attr +from .core import IFRAggregate, MultiHopIFRResult, compute_ifr_sentence_aggregate +``` + +- [ ] **Step 7: Replace root compatibility modules** + +Replace `lrp_rules.py` with: + +```python +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.lrp_rules import * # noqa: F401,F403 +``` + +Replace `lrp_patches.py` with: + +```python +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.lrp_patches import * # noqa: F401,F403 +``` + +Replace `llm_attr.py` with: + +```python +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.attribution import * # noqa: F401,F403 +``` + +Replace `ft_ifr_improve.py` with: + +```python +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.improved import * # noqa: F401,F403 +``` + +- [ ] **Step 8: Export the AttnLRP baseline** + +Replace `flashtrace/baselines/attnlrp.py` with: + +```python +"""AttnLRP baseline API.""" + +from flashtrace.attribution import AttnLRPSpanAggregate, LLMLRPAttribution, MultiHopAttnLRPResult +from flashtrace.lrp_patches import detect_model_type, lrp_context + +__all__ = [ + "AttnLRPSpanAggregate", + "LLMLRPAttribution", + "MultiHopAttnLRPResult", + "detect_model_type", + "lrp_context", +] +``` + +Replace `flashtrace/baselines/__init__.py` with: + +```python +"""Baseline attribution methods for FlashTrace.""" + +from .attnlrp import LLMLRPAttribution + +__all__ = ["LLMLRPAttribution"] +``` + +- [ ] **Step 9: Run attribution migration tests** + +Run: + +```bash +uv run pytest tests/test_core_recompute.py -q +``` + +Expected: all tests in the file pass. + +- [ ] **Step 10: Run a root compatibility import check** + +Run: + +```bash +uv run python -c "import ifr_core, llm_attr, ft_ifr_improve; print(llm_attr.LLMIFRAttribution.__name__)" +``` + +Expected: prints `LLMIFRAttribution`. + +- [ ] **Step 11: Commit** + +Run: + +```bash +git add flashtrace lrp_rules.py lrp_patches.py llm_attr.py ft_ifr_improve.py tests/test_core_recompute.py +git commit -m "feat: move attribution engines into package" +``` + +## Task 4: TraceResult And HTML Heatmap + +**Files:** +- Modify: `flashtrace/result.py` +- Create: `flashtrace/viz.py` +- Create: `tests/test_result.py` + +- [ ] **Step 1: Write result object tests** + +Create `tests/test_result.py`: + +```python +import json + +from flashtrace.result import TokenScore, TraceResult + + +def make_result(): + return TraceResult( + prompt_tokens=[" alpha", " beta", " gamma"], + generation_tokens=[" answer"], + scores=[0.2, 0.7, 0.1], + per_hop_scores=[[0.1, 0.4, 0.0], [0.1, 0.3, 0.1]], + thinking_ratios=[0.5, 0.2], + output_span=(0, 0), + reasoning_span=(0, 0), + method="flashtrace", + metadata={"model": "tiny"}, + ) + + +def test_topk_inputs_sorted(): + result = make_result() + + top = result.topk_inputs(2) + + assert top == [ + TokenScore(index=1, token=" beta", score=0.7), + TokenScore(index=0, token=" alpha", score=0.2), + ] + + +def test_to_dict_is_json_serializable(): + result = make_result() + + payload = result.to_dict() + + assert payload["method"] == "flashtrace" + assert payload["top_inputs"][0]["token"] == " beta" + json.dumps(payload) + + +def test_to_dict_sanitizes_tensor_metadata(): + import torch + + result = TraceResult( + prompt_tokens=[" alpha"], + generation_tokens=[" answer"], + scores=[1.0], + metadata={"tensor": torch.tensor([1.0, 2.0]), "object": object()}, + ) + + payload = result.to_dict() + + assert payload["metadata"]["tensor"] == [1.0, 2.0] + assert isinstance(payload["metadata"]["object"], str) + json.dumps(payload) + + +def test_json_and_html_export(tmp_path): + result = make_result() + json_path = tmp_path / "trace.json" + html_path = tmp_path / "trace.html" + + result.to_json(json_path) + result.to_html(html_path) + + assert json_path.read_text(encoding="utf-8").startswith("{") + html = html_path.read_text(encoding="utf-8") + assert " list[TokenScore]: + limit = max(0, int(k)) + items = [ + TokenScore(index=i, token=tok, score=float(score)) + for i, (tok, score) in enumerate(zip(self.prompt_tokens, self.scores)) + ] + items.sort(key=lambda item: item.score, reverse=True) + return items[:limit] + + def to_dict(self) -> dict[str, Any]: + return { + "method": self.method, + "prompt_tokens": list(self.prompt_tokens), + "generation_tokens": list(self.generation_tokens), + "scores": [float(x) for x in self.scores], + "per_hop_scores": [[float(x) for x in row] for row in self.per_hop_scores], + "thinking_ratios": [float(x) for x in self.thinking_ratios], + "output_span": list(self.output_span) if self.output_span is not None else None, + "reasoning_span": list(self.reasoning_span) if self.reasoning_span is not None else None, + "top_inputs": [asdict(item) for item in self.topk_inputs()], + "metadata": _jsonable(self.metadata), + } + + def to_json(self, path: str | Path) -> None: + target = Path(path) + target.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False), encoding="utf-8") + + def to_html(self, path: str | Path) -> None: + from .viz import render_trace_html + + target = Path(path) + target.write_text(render_trace_html(self), encoding="utf-8") + + +def _jsonable(value: Any) -> Any: + if value is None or isinstance(value, (str, int, float, bool)): + return value + if hasattr(value, "detach") and hasattr(value, "cpu"): + try: + return value.detach().cpu().tolist() + except Exception: + return repr(value) + if is_dataclass(value): + return _jsonable(asdict(value)) + if isinstance(value, dict): + return {str(k): _jsonable(v) for k, v in value.items()} + if isinstance(value, (list, tuple)): + return [_jsonable(v) for v in value] + return repr(value) +``` + +- [ ] **Step 4: Implement the standalone HTML renderer** + +Create `flashtrace/viz.py`: + +```python +from __future__ import annotations + +from html import escape +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from .result import TraceResult + + +def _score_color(score: float, max_score: float) -> str: + if max_score <= 0.0: + return "rgba(245,245,245,0.75)" + ratio = min(1.0, abs(float(score)) / (max_score + 1e-12)) + red = 255 + green = int(246 - 105 * ratio) + blue = int(226 - 170 * ratio) + alpha = 0.22 + 0.58 * ratio + return f"rgba({red},{green},{blue},{alpha:.3f})" + + +def _render_token_row(tokens: list[str], scores: list[float]) -> str: + max_score = max((abs(float(x)) for x in scores), default=0.0) + spans = [] + for index, token in enumerate(tokens): + score = float(scores[index]) if index < len(scores) else 0.0 + color = _score_color(score, max_score) + spans.append( + "{escape(token)}" + ) + return "".join(spans) + + +def render_trace_html(result: "TraceResult") -> str: + top_rows = "\n".join( + f"{item.index}{escape(item.token)}{item.score:.6f}" + for item in result.topk_inputs(20) + ) + hop_sections = [] + for hop_index, hop_scores in enumerate(result.per_hop_scores): + hop_sections.append( + f"

Hop {hop_index}

{_render_token_row(result.prompt_tokens, hop_scores)}
" + ) + hop_html = "\n".join(hop_sections) + metadata = escape(str(result.metadata)) + return f""" + + + + FlashTrace + + + +

FlashTrace

+

method={escape(result.method)} output_span={escape(str(result.output_span))} reasoning_span={escape(str(result.reasoning_span))}

+
+

Prompt Attribution

+
{_render_token_row(result.prompt_tokens, result.scores)}
+
+ {hop_html} +
+

Top Input Tokens

+ {top_rows}
IndexTokenScore
+
+
+

Metadata

+
{metadata}
+
+ + +""" +``` + +- [ ] **Step 5: Run result tests** + +Run: + +```bash +uv run pytest tests/test_result.py -q +``` + +Expected: `4 passed`. + +- [ ] **Step 6: Commit** + +Run: + +```bash +git add flashtrace/result.py flashtrace/viz.py tests/test_result.py +git commit -m "feat: add trace result exports" +``` + +## Task 5: FlashTrace Facade + +**Files:** +- Modify: `flashtrace/tracer.py` +- Modify: `flashtrace/__init__.py` +- Create: `tests/test_tracer.py` + +- [ ] **Step 1: Write tracer API tests** + +Create `tests/test_tracer.py`: + +```python +from flashtrace import FlashTrace, TraceResult +from tests.helpers import make_tiny_qwen2_model_and_tokenizer + + +def test_flashtrace_trace_returns_public_result(): + model, tokenizer = make_tiny_qwen2_model_and_tokenizer(n_layers=2, d_model=32, n_heads=4, n_kv_heads=2) + tracer = FlashTrace(model, tokenizer, chunk_tokens=16, sink_chunk_tokens=4, recompute_attention=True) + + result = tracer.trace( + prompt="t10 t20 t30 t40", + target="t60 t70 t80", + output_span=(1, 2), + reasoning_span=(0, 1), + hops=1, + ) + + assert isinstance(result, TraceResult) + assert result.method == "flashtrace" + assert len(result.prompt_tokens) > 0 + assert len(result.scores) == len(result.prompt_tokens) + assert result.output_span == (1, 2) + assert result.reasoning_span == (0, 1) + + +def test_ifr_span_method_returns_public_result(): + model, tokenizer = make_tiny_qwen2_model_and_tokenizer(n_layers=2, d_model=32, n_heads=4, n_kv_heads=2) + tracer = FlashTrace(model, tokenizer, chunk_tokens=16, sink_chunk_tokens=4, recompute_attention=True) + + result = tracer.trace( + prompt="t10 t20 t30 t40", + target="t60 t70", + output_span=(0, 1), + method="ifr-span", + ) + + assert result.method == "ifr-span" + assert len(result.scores) == len(result.prompt_tokens) +``` + +- [ ] **Step 2: Run tracer tests and see the expected failure** + +Run: + +```bash +uv run pytest tests/test_tracer.py -q +``` + +Expected: pytest reports missing `trace`. + +- [ ] **Step 3: Implement result adaptation helpers and facade** + +Replace `flashtrace/tracer.py` with: + +```python +from __future__ import annotations + +from typing import Any, Literal + +import torch + +from .attribution import LLMIFRAttribution, LLMAttributionResult +from .improved import LLMIFRAttributionBoth +from .result import TraceResult + +TraceMethod = Literal["flashtrace", "ifr-span", "ifr-matrix"] + + +def _to_float_list(values: Any) -> list[float]: + if torch.is_tensor(values): + values = values.detach().cpu().to(dtype=torch.float32).tolist() + return [float(x) for x in (values or [])] + + +class FlashTrace: + """Public facade for FlashTrace attribution.""" + + def __init__( + self, + model, + tokenizer, + *, + chunk_tokens: int = 128, + sink_chunk_tokens: int = 32, + recompute_attention: bool = False, + generate_kwargs: dict[str, Any] | None = None, + ) -> None: + self.model = model + self.tokenizer = tokenizer + self.chunk_tokens = int(chunk_tokens) + self.sink_chunk_tokens = int(sink_chunk_tokens) + self.recompute_attention = bool(recompute_attention) + self.generate_kwargs = generate_kwargs + + def trace( + self, + *, + prompt: str, + target: str | None = None, + output_span: tuple[int, int] | None = None, + reasoning_span: tuple[int, int] | None = None, + hops: int = 1, + method: TraceMethod = "flashtrace", + renorm_threshold: float | None = None, + ) -> TraceResult: + if method == "flashtrace": + engine = LLMIFRAttributionBoth( + self.model, + self.tokenizer, + generate_kwargs=self.generate_kwargs, + chunk_tokens=self.chunk_tokens, + sink_chunk_tokens=self.sink_chunk_tokens, + recompute_attention=self.recompute_attention, + ) + raw = engine.calculate_ifr_multi_hop_both( + prompt, + target=target, + sink_span=output_span, + thinking_span=reasoning_span, + n_hops=int(hops), + renorm_threshold=renorm_threshold, + ) + elif method == "ifr-span": + engine = LLMIFRAttribution( + self.model, + self.tokenizer, + generate_kwargs=self.generate_kwargs, + chunk_tokens=self.chunk_tokens, + sink_chunk_tokens=self.sink_chunk_tokens, + recompute_attention=self.recompute_attention, + ) + raw = engine.calculate_ifr_span( + prompt, + target=target, + span=output_span, + renorm_threshold=renorm_threshold, + ) + elif method == "ifr-matrix": + engine = LLMIFRAttribution( + self.model, + self.tokenizer, + generate_kwargs=self.generate_kwargs, + chunk_tokens=self.chunk_tokens, + sink_chunk_tokens=self.sink_chunk_tokens, + recompute_attention=self.recompute_attention, + ) + raw = engine.calculate_ifr_for_all_positions_output_only( + prompt, + target=target, + sink_span=output_span, + renorm_threshold=renorm_threshold, + ) + else: + raise ValueError(f"Unsupported method: {method}") + + return self._build_result(raw, method=method, output_span=output_span, reasoning_span=reasoning_span) + + def _build_result( + self, + raw: LLMAttributionResult, + *, + method: str, + output_span: tuple[int, int] | None, + reasoning_span: tuple[int, int] | None, + ) -> TraceResult: + prompt_tokens = list(raw.prompt_tokens) + generation_tokens = list(raw.generation_tokens) + prompt_len = len(prompt_tokens) + metadata = dict(raw.metadata or {}) + if "method" not in metadata: + metadata["method"] = method + + ifr_meta = metadata.get("ifr") if isinstance(metadata.get("ifr"), dict) else {} + observation = ifr_meta.get("observation_projected") if isinstance(ifr_meta, dict) else None + per_hop_projected = ifr_meta.get("per_hop_projected") if isinstance(ifr_meta, dict) else None + + if isinstance(observation, dict) and "sum" in observation: + vector = _to_float_list(observation["sum"]) + scores = vector[:prompt_len] + else: + matrix = torch.nan_to_num(raw.attribution_matrix.detach().cpu().to(dtype=torch.float32), nan=0.0) + if output_span is not None: + start, end = output_span + selected = matrix[int(start) : int(end) + 1, :prompt_len] + else: + selected = matrix[:, :prompt_len] + scores = selected.mean(dim=0).tolist() if selected.numel() else [0.0 for _ in prompt_tokens] + + per_hop_scores: list[list[float]] = [] + if per_hop_projected: + for hop_vector in per_hop_projected: + per_hop_scores.append(_to_float_list(hop_vector)[:prompt_len]) + + ratios = ifr_meta.get("thinking_ratios", []) if isinstance(ifr_meta, dict) else [] + return TraceResult( + prompt_tokens=prompt_tokens, + generation_tokens=generation_tokens, + scores=[float(x) for x in scores], + per_hop_scores=per_hop_scores, + thinking_ratios=_to_float_list(ratios), + output_span=output_span, + reasoning_span=reasoning_span, + method=method, + metadata=metadata, + ) +``` + +- [ ] **Step 4: Confirm public exports** + +Keep `flashtrace/__init__.py` as: + +```python +"""FlashTrace: efficient multi-token attribution for reasoning LLMs.""" + +from .model_io import load_model_and_tokenizer +from .result import TokenScore, TraceResult +from .tracer import FlashTrace + +__all__ = ["FlashTrace", "TraceResult", "TokenScore", "load_model_and_tokenizer"] +``` + +- [ ] **Step 5: Run tracer tests** + +Run: + +```bash +uv run pytest tests/test_tracer.py -q +``` + +Expected: `2 passed`. + +- [ ] **Step 6: Run package tests created so far** + +Run: + +```bash +uv run pytest tests/test_imports.py tests/test_core_recompute.py tests/test_result.py tests/test_tracer.py -q +``` + +Expected: all selected tests pass. + +- [ ] **Step 7: Commit** + +Run: + +```bash +git add flashtrace/tracer.py flashtrace/__init__.py tests/test_tracer.py +git commit -m "feat: add FlashTrace public facade" +``` + +## Task 6: Model IO And CLI + +**Files:** +- Modify: `flashtrace/model_io.py` +- Modify: `flashtrace/cli.py` +- Create: `tests/test_cli.py` + +- [ ] **Step 1: Write CLI tests** + +Create `tests/test_cli.py`: + +```python +import pytest + +from flashtrace.cli import main, parse_span + + +def test_parse_span(): + assert parse_span("3:8") == (3, 8) + assert parse_span(None) is None + + +@pytest.mark.parametrize("value", ["3", "8:3", "a:b"]) +def test_parse_span_rejects_invalid_values(value): + with pytest.raises(ValueError): + parse_span(value) + + +def test_cli_help_exits_successfully(capsys): + with pytest.raises(SystemExit) as exc: + main(["--help"]) + + assert exc.value.code == 0 + assert "trace" in capsys.readouterr().out +``` + +- [ ] **Step 2: Run CLI tests and see the expected failure** + +Run: + +```bash +uv run pytest tests/test_cli.py -q +``` + +Expected: pytest reports missing `parse_span`. + +- [ ] **Step 3: Implement model loading** + +Replace `flashtrace/model_io.py` with: + +```python +from __future__ import annotations + +from typing import Any + +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer + + +def _resolve_dtype(dtype: str | torch.dtype = "auto") -> str | torch.dtype: + if isinstance(dtype, torch.dtype): + return dtype + value = str(dtype).lower() + if value == "auto": + return "auto" + mapping = { + "float16": torch.float16, + "fp16": torch.float16, + "bfloat16": torch.bfloat16, + "bf16": torch.bfloat16, + "float32": torch.float32, + "fp32": torch.float32, + } + if value not in mapping: + raise ValueError(f"Unsupported dtype: {dtype}") + return mapping[value] + + +def load_model_and_tokenizer( + model_name_or_path: str, + *, + device_map: str | dict[str, Any] | None = "auto", + dtype: str | torch.dtype = "auto", + trust_remote_code: bool = True, + **model_kwargs: Any, +): + """Load a Hugging Face causal LM and matching tokenizer.""" + + tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, trust_remote_code=trust_remote_code) + model = AutoModelForCausalLM.from_pretrained( + model_name_or_path, + torch_dtype=_resolve_dtype(dtype), + device_map=device_map, + trust_remote_code=trust_remote_code, + **model_kwargs, + ) + model.eval() + if tokenizer.pad_token_id is None and tokenizer.eos_token_id is not None: + tokenizer.pad_token = tokenizer.eos_token + return model, tokenizer +``` + +- [ ] **Step 4: Implement CLI** + +Replace `flashtrace/cli.py` with: + +```python +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Sequence + +from .model_io import load_model_and_tokenizer +from .tracer import FlashTrace + + +def parse_span(value: str | None) -> tuple[int, int] | None: + if value is None: + return None + parts = str(value).split(":") + if len(parts) != 2: + raise ValueError("Span must use START:END format.") + try: + start = int(parts[0]) + end = int(parts[1]) + except ValueError as exc: + raise ValueError("Span bounds must be integers.") from exc + if start < 0 or end < start: + raise ValueError("Span must satisfy 0 <= START <= END.") + return start, end + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(prog="flashtrace", description="Trace language model outputs with FlashTrace.") + sub = parser.add_subparsers(dest="command") + + trace = sub.add_parser("trace", help="Run attribution for a prompt and target.") + trace.add_argument("--model", required=True, help="Hugging Face model id or local path.") + trace.add_argument("--prompt", required=True, help="UTF-8 text file containing the prompt.") + trace.add_argument("--target", help="UTF-8 text file containing the target response.") + trace.add_argument("--output-span", help="Inclusive generation-token span START:END.") + trace.add_argument("--reasoning-span", help="Inclusive generation-token span START:END.") + trace.add_argument("--hops", type=int, default=1) + trace.add_argument("--method", default="flashtrace", choices=["flashtrace", "ifr-span", "ifr-matrix"]) + trace.add_argument("--html", help="Write standalone HTML heatmap.") + trace.add_argument("--json", help="Write JSON trace.") + trace.add_argument("--device-map", default="auto") + trace.add_argument("--dtype", default="auto", choices=["auto", "float16", "bfloat16", "float32"]) + trace.add_argument("--chunk-tokens", type=int, default=128) + trace.add_argument("--sink-chunk-tokens", type=int, default=32) + trace.add_argument("--recompute-attention", action="store_true") + return parser + + +def _read_text(path: str | None) -> str | None: + if path is None: + return None + return Path(path).read_text(encoding="utf-8") + + +def _run_trace(args: argparse.Namespace) -> int: + model, tokenizer = load_model_and_tokenizer(args.model, device_map=args.device_map, dtype=args.dtype) + tracer = FlashTrace( + model, + tokenizer, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + recompute_attention=args.recompute_attention, + ) + result = tracer.trace( + prompt=_read_text(args.prompt) or "", + target=_read_text(args.target), + output_span=parse_span(args.output_span), + reasoning_span=parse_span(args.reasoning_span), + hops=args.hops, + method=args.method, + ) + for item in result.topk_inputs(20): + print(f"{item.index}\t{item.score:.6f}\t{item.token!r}") + if args.json: + result.to_json(args.json) + if args.html: + result.to_html(args.html) + return 0 + + +def main(argv: Sequence[str] | None = None) -> int: + parser = build_parser() + args = parser.parse_args(argv) + if args.command == "trace": + return _run_trace(args) + parser.print_help() + return 0 +``` + +- [ ] **Step 5: Run CLI tests** + +Run: + +```bash +uv run pytest tests/test_cli.py -q +``` + +Expected: all CLI tests pass. + +- [ ] **Step 6: Verify console script metadata** + +Run: + +```bash +uv run flashtrace --help +``` + +Expected: help text includes `trace`. + +- [ ] **Step 7: Commit** + +Run: + +```bash +git add flashtrace/model_io.py flashtrace/cli.py tests/test_cli.py +git commit -m "feat: add model loader and CLI" +``` + +## Task 7: README, Example, License, And Release Hygiene + +**Files:** +- Create: `README.md` +- Create: `LICENSE` +- Create: `examples/quickstart.py` +- Modify: `.gitignore` +- Delete: `model_generation.py` + +- [ ] **Step 1: Create the quickstart example** + +Create `examples/quickstart.py`: + +```python +from __future__ import annotations + +import argparse + +from flashtrace import FlashTrace, load_model_and_tokenizer + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="FlashTrace quickstart example.") + parser.add_argument("--model", required=True, help="Hugging Face model id or local model path.") + parser.add_argument("--prompt", required=True, help="Prompt text.") + parser.add_argument("--target", help="Target response text.") + parser.add_argument("--output-span", default=None, help="Inclusive generation-token span START:END.") + parser.add_argument("--reasoning-span", default=None, help="Inclusive generation-token span START:END.") + parser.add_argument("--html", default="trace.html", help="Output HTML path.") + return parser + + +def parse_span(value: str | None) -> tuple[int, int] | None: + from flashtrace.cli import parse_span as parse_cli_span + + return parse_cli_span(value) + + +def main() -> int: + args = build_parser().parse_args() + model, tokenizer = load_model_and_tokenizer(args.model) + tracer = FlashTrace(model, tokenizer) + trace = tracer.trace( + prompt=args.prompt, + target=args.target, + output_span=parse_span(args.output_span), + reasoning_span=parse_span(args.reasoning_span), + ) + for item in trace.topk_inputs(10): + print(f"{item.index}\t{item.score:.6f}\t{item.token!r}") + trace.to_html(args.html) + print(f"wrote {args.html}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) +``` + +- [ ] **Step 2: Add README** + +Create `README.md`: + +```markdown +# FlashTrace + +FlashTrace is an efficient multi-token attribution toolkit for reasoning language models. It implements the method described in [Towards Long-Horizon Interpretability: Efficient and Faithful Multi-Token Attribution for Reasoning LLMs](https://arxiv.org/abs/2602.01914). + +## Install + +```bash +pip install -e . +``` + +## Python Quickstart + +```python +from flashtrace import FlashTrace, load_model_and_tokenizer + +model, tokenizer = load_model_and_tokenizer("Qwen/Qwen3-8B") +tracer = FlashTrace(model, tokenizer) + +trace = tracer.trace( + prompt="Context: Paris is the capital of France.\nQuestion: What is the capital of France?", + target="Paris", + output_span=(0, 0), + hops=1, +) + +print(trace.topk_inputs(10)) +trace.to_html("trace.html") +trace.to_json("trace.json") +``` + +## CLI Quickstart + +```bash +flashtrace trace \ + --model Qwen/Qwen3-8B \ + --prompt prompt.txt \ + --target target.txt \ + --output-span 0:0 \ + --hops 1 \ + --html trace.html \ + --json trace.json +``` + +## Token Spans + +`output_span` and `reasoning_span` use inclusive generation-token indices. Inspect `trace.generation_tokens` after an initial run to choose spans for a target answer or reasoning segment. + +## Supported Models + +The package targets Llama/Qwen-style decoder-only Hugging Face causal LMs with standard Q/K/V/O projections, RMSNorm or LayerNorm, and RoPE metadata. Qwen2, Qwen3, and Llama are the first validated model families. + +## Repository Map + +- `flashtrace/`: reusable package +- `examples/`: public examples +- `tests/`: CPU smoke tests +- `exp/`: paper experiments and artifacts + +## Citation + +```bibtex +@misc{pan2026flashtrace, + title={Towards Long-Horizon Interpretability: Efficient and Faithful Multi-Token Attribution for Reasoning LLMs}, + author={Pan, Wenbo and Liu, Zhichao and Wang, Xianlong and Yu, Haining and Jia, Xiaohua}, + year={2026}, + eprint={2602.01914}, + archivePrefix={arXiv}, + primaryClass={cs.LG} +} +``` +``` + +- [ ] **Step 3: Add MIT license** + +Create `LICENSE`: + +```text +MIT License + +Copyright (c) 2026 Wenbo Pan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + +- [ ] **Step 4: Update generated artifact ignore rules** + +Append to `.gitignore`: + +```gitignore + +# FlashTrace generated artifacts +trace.json +trace.html +*.trace.json +*.trace.html +exp/**/output/ +exp/**/out/ +exp/**/out-*/ +*.npz +``` + +- [ ] **Step 5: Remove the template artifact** + +Run: + +```bash +git rm model_generation.py +``` + +- [ ] **Step 6: Verify quickstart help** + +Run: + +```bash +uv run python examples/quickstart.py --help +``` + +Expected: help text includes `FlashTrace quickstart example`. + +- [ ] **Step 7: Commit** + +Run: + +```bash +git add README.md LICENSE examples/quickstart.py .gitignore +git commit -m "docs: add public quickstart and release hygiene" +``` + +## Task 8: Final Verification And Package Audit + +**Files:** +- Modify: any files needed to fix verification failures. + +- [ ] **Step 1: Run the full CPU test suite** + +Run: + +```bash +uv run pytest tests -q +``` + +Expected: all tests pass. + +- [ ] **Step 2: Verify editable install import** + +Run: + +```bash +uv run python -c "import flashtrace; print(flashtrace.FlashTrace.__name__)" +``` + +Expected: prints `FlashTrace`. + +- [ ] **Step 3: Verify CLI help** + +Run: + +```bash +uv run flashtrace --help +uv run flashtrace trace --help +``` + +Expected: both commands print help text. + +- [ ] **Step 4: Verify root compatibility imports** + +Run: + +```bash +uv run python -c "import ifr_core, llm_attr, ft_ifr_improve; print(ifr_core.compute_multi_hop_ifr.__name__)" +``` + +Expected: prints `compute_multi_hop_ifr`. + +- [ ] **Step 5: Inspect package file list** + +Run: + +```bash +git status --short +find flashtrace -maxdepth 3 -type f | sort +``` + +Expected: package files match the design spec and only intended changes appear. + +- [ ] **Step 6: Commit final fixes** + +Run after any verification fixes: + +```bash +git add . +git commit -m "test: verify public package smoke tests" +``` + +If verification passes with a clean tree after prior commits, record the passing commands in the final implementation response. + +## Self-Review Checklist + +- Spec coverage: package layout, public API, result export, CLI, visualization, packaging, compatibility, tests, README, and release hygiene each have at least one task. +- Type consistency: `FlashTrace.trace`, `TraceResult`, `TokenScore`, `load_model_and_tokenizer`, and CLI span parsing use the same names across tests and implementation steps. +- Test path: every implementation task starts with a failing test or a verification command, then ends with a passing command and commit. diff --git a/docs/superpowers/specs/2026-05-03-flashtrace-public-package-design.md b/docs/superpowers/specs/2026-05-03-flashtrace-public-package-design.md new file mode 100644 index 0000000000000000000000000000000000000000..8c500bead8fcfe2334af169a17f7af2892e75c36 --- /dev/null +++ b/docs/superpowers/specs/2026-05-03-flashtrace-public-package-design.md @@ -0,0 +1,231 @@ +# FlashTrace Public Package Design + +## Goal + +Turn the current FlashTrace research repository into an installable, documented Python package that researchers can use from Python or the command line to trace LLM outputs, export JSON traces, and render HTML token heatmaps. + +## Release Scope + +This first public release ships four user-facing capabilities: + +- A stable Python API centered on `FlashTrace`. +- A `flashtrace trace` CLI for prompt/target files and Hugging Face model ids or local model paths. +- A `TraceResult` object with top-k, JSON, and HTML export helpers. +- A README quickstart that demonstrates Python, CLI, and heatmap workflows. + +Paper experiment runners and saved experiment artifacts remain in `exp/` as research assets. Their full reproducibility cleanup belongs to a later phase. + +## Repository Shape + +The reusable package lives under `flashtrace/`, examples under `examples/`, tests under `tests/`, and paper experiments under `exp/`. + +```text +flashtrace/ + __init__.py + tracer.py + result.py + core.py + model_io.py + viz.py + cli.py + baselines/ + __init__.py + attnlrp.py +examples/ + quickstart.py +tests/ + test_core_recompute.py + test_tracer.py + test_result.py + test_cli.py +exp/ + exp1/ + exp2/ + case_study/ +``` + +Existing root modules are migrated gradually. During migration, compatibility wrappers remain at the root for experiment scripts that still import `llm_attr`, `ifr_core`, or `ft_ifr_improve`. + +## Core Implementation Mapping + +`flashtrace.core` contains the IFR tensor implementation from `ifr_core.py`: + +- `extract_model_metadata` +- `build_weight_pack` +- `attach_hooks` +- `recompute_layer_attention` +- `compute_ifr_sentence_aggregate` +- `compute_multi_hop_ifr` +- `compute_ifr_for_all_positions` + +`flashtrace.tracer` wraps the current high-level attribution classes: + +- Default `method="flashtrace"` uses the current `LLMIFRAttributionBoth.calculate_ifr_multi_hop_both` behavior. +- `method="ifr-span"` uses `LLMIFRAttribution.calculate_ifr_span`. +- `method="ifr-matrix"` uses `LLMIFRAttribution.calculate_ifr_for_all_positions_output_only`. + +`flashtrace.baselines.attnlrp` contains the AttnLRP patching and recursive baseline code from `lrp_rules.py`, `lrp_patches.py`, and `LLMLRPAttribution`. + +## Public Python API + +The package exports `FlashTrace`, `TraceResult`, and `load_model_and_tokenizer`. + +```python +from flashtrace import FlashTrace, load_model_and_tokenizer + +model, tokenizer = load_model_and_tokenizer("Qwen/Qwen3-8B", device_map="auto") +tracer = FlashTrace(model, tokenizer, chunk_tokens=128, sink_chunk_tokens=32) + +trace = tracer.trace( + prompt=prompt, + target=target, + output_span=(80, 85), + reasoning_span=(0, 79), + hops=1, +) + +print(trace.topk_inputs(20)) +trace.to_json("trace.json") +trace.to_html("trace.html") +``` + +`FlashTrace.trace(...)` accepts: + +- `prompt: str` +- `target: str | None` +- `output_span: tuple[int, int] | None` +- `reasoning_span: tuple[int, int] | None` +- `hops: int` +- `method: Literal["flashtrace", "ifr-span", "ifr-matrix"]` +- `renorm_threshold: float | None` + +Generation-token spans are inclusive and use the tokenizer alignment already produced by the attribution path. The README explains this convention and shows how to inspect `trace.generation_tokens`. + +## TraceResult + +`TraceResult` is a small dataclass that hides the older `LLMAttributionResult` shape from public users. + +Fields: + +- `prompt_tokens: list[str]` +- `generation_tokens: list[str]` +- `scores: list[float]` +- `per_hop_scores: list[list[float]]` +- `thinking_ratios: list[float]` +- `output_span: tuple[int, int] | None` +- `reasoning_span: tuple[int, int] | None` +- `method: str` +- `metadata: dict[str, Any]` + +Methods: + +- `topk_inputs(k: int = 20) -> list[TokenScore]` +- `to_dict() -> dict[str, Any]` +- `to_json(path: str | Path) -> None` +- `to_html(path: str | Path) -> None` + +`TokenScore` contains `index`, `token`, and `score`. Scores are aligned to `prompt_tokens`. + +## CLI + +The package exposes one console script: + +```bash +flashtrace trace \ + --model Qwen/Qwen3-8B \ + --prompt prompt.txt \ + --target target.txt \ + --output-span 80:85 \ + --reasoning-span 0:79 \ + --hops 1 \ + --html trace.html \ + --json trace.json +``` + +CLI behavior: + +- `--model` accepts a Hugging Face id or local path. +- `--prompt` and `--target` read UTF-8 text files. +- `--target` is optional; the model generates with deterministic defaults when this flag is absent. +- `--output-span` and `--reasoning-span` parse inclusive `START:END` generation-token spans. +- `--method` defaults to `flashtrace`. +- `--recompute-attention` enables lower-memory attention recomputation. +- `--device-map` defaults to `auto`. +- `--dtype` accepts `auto`, `float16`, `bfloat16`, or `float32`. + +The command prints a compact top-k table to stdout and writes requested artifacts. + +## Visualization + +`flashtrace.viz` adapts the token heatmap renderer from `exp/case_study/viz.py`. + +The public heatmap focuses on: + +- prompt tokens colored by final attribution score, +- optional per-hop panels, +- output and reasoning span summary, +- model/method metadata. + +The renderer returns a standalone HTML string and writes standalone HTML files through `TraceResult.to_html`. + +## Packaging + +`pyproject.toml` becomes package metadata for `flashtrace`: + +- `name = "flashtrace"` +- realistic `requires-python` support for current PyTorch and Transformers use, +- console script `flashtrace = "flashtrace.cli:main"`, +- core dependencies: `torch`, `transformers`, `accelerate`, `numpy`, `tqdm`, +- optional extras: `viz`, `eval`, `dev`, `baselines`. + +The root README includes: + +- project tagline, +- paper link and citation, +- install instructions, +- Python quickstart, +- CLI quickstart, +- supported model family notes, +- output interpretation, +- experiment directory map, +- troubleshooting for GPU memory and tokenizer spans. + +## Compatibility + +The release supports Llama/Qwen-style decoder-only Hugging Face causal LMs with `model.layers`, Q/K/V/O projections, RMSNorm/LayerNorm, and RoPE metadata. The README names Qwen2, Qwen3, and Llama as validated families. + +Existing experiment scripts continue to run through temporary root-level compatibility modules while package imports are introduced. A later cleanup can remove the compatibility layer after `exp/` imports are migrated. + +## Testing + +Tests use a tiny randomly initialized Qwen2 model on CPU, following the existing `test_recompute.py` approach. + +Required coverage: + +- stored-attention and recomputed-attention paths return close values on the tiny model, +- `FlashTrace.trace(...)` returns a `TraceResult`, +- `TraceResult.topk_inputs(...)` sorts and truncates correctly, +- `TraceResult.to_dict()` is JSON serializable, +- `TraceResult.to_html()` writes standalone HTML containing token spans, +- `flashtrace trace --help` exits successfully. + +Heavy GPU model tests remain manual examples. + +## Release Hygiene + +The release cleanup updates `.gitignore` to cover generated traces, experiment outputs, checkpoints, caches, and HTML/JSON artifacts created by examples. + +Tracked historical experiment outputs stay untouched during the first package migration. A later artifact cleanup can move them to release assets or remove them with a dedicated confirmation step. + +`model_generation.py` is a template artifact and is removed or moved outside the package path during implementation. + +## Success Criteria + +The release work is complete when: + +- `pip install -e .` exposes `flashtrace`, +- `python examples/quickstart.py --help` works, +- `flashtrace trace --help` works, +- package smoke tests pass on CPU, +- README quickstart matches the implemented API, +- existing experiment entrypoints either run with compatibility imports or document their package-era invocation. diff --git a/dump_exp2_hop_vh.py b/dump_exp2_hop_vh.py new file mode 100644 index 0000000000000000000000000000000000000000..4c352b3beac02015a61ae86f748f8a9c4ce0b1a9 --- /dev/null +++ b/dump_exp2_hop_vh.py @@ -0,0 +1,412 @@ +#!/usr/bin/env python3 +"""One-off: add per-hop IFR vectors (vh) into an existing exp2 trace .npz. + +This is useful when the original exp2 run saved sample-level traces but did not +include per-hop vectors for some multi-hop IFR variants (e.g. ifr_multi_hop_both). + +Defaults are written to match the reference commands in `exp/exp2/README.md`. + +Example (matches the path in the question): + +python dump_exp2_hop_vh.py \ + --trace_npz exp/exp2/output/traces/exp/exp2/data/morehopqa.jsonl/qwen-8B/ifr_multi_hop_both_n1_mfaithfulness_gen_95ex/ex_000026.npz \ + --dataset exp/exp2/data/morehopqa.jsonl \ + --attr_func ifr_multi_hop_both \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 2,3,4,5,6,7 \ + --n_hops 1 \ + --chunk_tokens 128 \ + --sink_chunk_tokens 32 \ + --inplace +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +import re +import sys +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Optional + + +def _early_set_cuda_visible_devices() -> None: + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("--cuda", type=str, default=None) + args, _ = parser.parse_known_args(sys.argv[1:]) + if args.cuda and "," in str(args.cuda): + os.environ["CUDA_VISIBLE_DEVICES"] = str(args.cuda) + + +_early_set_cuda_visible_devices() + +import numpy as np +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer + +import ft_ifr_improve +import llm_attr +from exp.exp2 import dataset_utils as ds_utils + + +def _sha1_text(text: str) -> str: + return hashlib.sha1(text.encode("utf-8")).hexdigest() + + +def _resolve_device(cuda: Optional[str], cuda_num: int) -> str: + """Mirror exp/exp2/run_exp.py device selection policy.""" + if cuda is not None and "," in cuda: + # _early_set_cuda_visible_devices already applied. + return "auto" + if cuda is not None and str(cuda).strip(): + return f"cuda:{cuda}" if torch.cuda.is_available() else "cpu" + return f"cuda:{int(cuda_num)}" if torch.cuda.is_available() else "cpu" + + +def _load_model(model_name: str, device: str): + """Mirror exp/exp2/run_exp.py model loading knobs.""" + model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map="auto" if device == "auto" else {"": int(device.split(":")[1])} if device.startswith("cuda:") else None, + torch_dtype=torch.float16, + attn_implementation="eager", + ) + tokenizer = AutoTokenizer.from_pretrained(model_name) + tokenizer.pad_token = tokenizer.eos_token + model.eval() + return model, tokenizer + + +@dataclass(frozen=True) +class ManifestRecord: + example_idx: int + prompt_sha1: str + target_sha1: Optional[str] + + +def _load_manifest_record(manifest_path: Path, *, example_idx: int) -> Optional[ManifestRecord]: + if not manifest_path.exists(): + return None + with manifest_path.open("r", encoding="utf-8") as f: + for line in f: + if not line.strip(): + continue + obj = json.loads(line) + if int(obj.get("example_idx", -1)) != int(example_idx): + continue + return ManifestRecord( + example_idx=int(example_idx), + prompt_sha1=str(obj.get("prompt_sha1") or ""), + target_sha1=str(obj["target_sha1"]) if obj.get("target_sha1") is not None else None, + ) + return None + + +def _parse_example_idx_from_npz_name(path: Path) -> Optional[int]: + m = re.match(r"^ex_(\d+)$", path.stem) + if not m: + return None + try: + return int(m.group(1)) + except Exception: + return None + + +def _pick_example( + examples: list[ds_utils.CachedExample], + *, + example_idx: int, + record: Optional[ManifestRecord], +) -> ds_utils.CachedExample: + if record is not None and record.prompt_sha1: + matches: list[ds_utils.CachedExample] = [] + for ex in examples: + if _sha1_text(ex.prompt) != record.prompt_sha1: + continue + if record.target_sha1 is None: + if ex.target is None: + matches.append(ex) + else: + if ex.target is not None and _sha1_text(ex.target) == record.target_sha1: + matches.append(ex) + if len(matches) == 1: + return matches[0] + if len(matches) > 1: + raise SystemExit( + f"Manifest sha1 matched multiple dataset entries ({len(matches)}). " + "Please pass --example_idx to select by index or use a smaller dataset cache." + ) + raise SystemExit( + "Failed to locate the trace example in the provided dataset by sha1. " + "Ensure --dataset points to the same cached JSONL used to produce the trace." + ) + + if not (0 <= int(example_idx) < len(examples)): + raise SystemExit(f"example_idx out of range: {example_idx} not in [0, {len(examples)}).") + return examples[int(example_idx)] + + +def _extract_vh(attr: Any) -> np.ndarray: + ifr = (getattr(attr, "metadata", None) or {}).get("ifr") or {} + per_hop = ifr.get("per_hop_projected") or [] + if not per_hop: + raise RuntimeError("Attribution result missing metadata['ifr']['per_hop_projected']; cannot build vh.") + stacked = torch.stack([torch.as_tensor(v, dtype=torch.float32).reshape(-1) for v in per_hop], dim=0) + return stacked.detach().cpu().numpy().astype(np.float32, copy=False) + + +def _run_ifr_attr( + attr_func: str, + *, + model: Any, + tokenizer: Any, + prompt: str, + target: str, + sink_span: Optional[tuple[int, int]], + thinking_span: Optional[tuple[int, int]], + n_hops: int, + chunk_tokens: int, + sink_chunk_tokens: int, +) -> Any: + if attr_func == "ifr_multi_hop": + attributor = llm_attr.LLMIFRAttribution( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + return attributor.calculate_ifr_multi_hop( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(n_hops), + ) + if attr_func == "ifr_in_all_gen": + attributor = ft_ifr_improve.LLMIFRAttributionInAllGen( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + return attributor.calculate_ifr_in_all_gen( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(n_hops), + ) + if attr_func == "ifr_multi_hop_stop_words": + attributor = ft_ifr_improve.LLMIFRAttributionImproved( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + return attributor.calculate_ifr_multi_hop_stop_words( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(n_hops), + ) + if attr_func == "ifr_multi_hop_both": + attributor = ft_ifr_improve.LLMIFRAttributionBoth( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + return attributor.calculate_ifr_multi_hop_both( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(n_hops), + ) + if attr_func == "ifr_multi_hop_split_hop": + attributor = ft_ifr_improve.LLMIFRAttributionSplitHop( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + return attributor.calculate_ifr_multi_hop_split_hop( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(n_hops), + ) + raise SystemExit( + f"Unsupported --attr_func '{attr_func}'. " + "Supported (vh-capable IFR variants): " + "ifr_multi_hop, ifr_in_all_gen, ifr_multi_hop_stop_words, ifr_multi_hop_both, ifr_multi_hop_split_hop." + ) + + +def _save_npz( + out_path: Path, + *, + payload: dict[str, np.ndarray], + inplace_src: Optional[Path] = None, + backup: bool = True, + overwrite_backup: bool = False, +) -> None: + out_path.parent.mkdir(parents=True, exist_ok=True) + if inplace_src is not None: + if backup and inplace_src.exists(): + backup_path = inplace_src.with_name(inplace_src.name + ".bak") + if overwrite_backup and backup_path.exists(): + backup_path.unlink() + if not backup_path.exists(): + backup_path.write_bytes(inplace_src.read_bytes()) + + # NOTE: numpy.savez* appends ".npz" if the filename does not already end with ".npz". + # So we must ensure our temporary path ends with ".npz", otherwise we'd write + # ".tmp.npz" but later try to os.replace(".tmp", ...). + tmp_path = out_path.with_name(out_path.stem + ".tmp.npz") + if tmp_path.exists(): + tmp_path.unlink() + np.savez_compressed(tmp_path, **payload) + os.replace(tmp_path, out_path) + return + + if out_path.exists(): + raise SystemExit(f"Refusing to overwrite existing file: {out_path} (use --inplace).") + np.savez_compressed(out_path, **payload) + + +def main() -> None: + parser = argparse.ArgumentParser("One-off exp2 trace patcher: add per-hop vh vectors.") + parser.add_argument( + "--trace_npz", + type=str, + default=( + "exp/exp2/output/traces/exp/exp2/data/morehopqa.jsonl/qwen-8B/" + "ifr_multi_hop_both_n1_mfaithfulness_gen_95ex/ex_000026.npz" + ), + help="Path to the existing exp2 trace npz (ex_*.npz).", + ) + parser.add_argument( + "--dataset", + type=str, + default="exp/exp2/data/morehopqa.jsonl", + help="Path to the exp2 cached dataset JSONL used to produce the trace.", + ) + parser.add_argument( + "--attr_func", + type=str, + default="ifr_multi_hop_both", + help="Attribution method to rerun (vh-capable IFR variants only).", + ) + parser.add_argument("--example_idx", type=int, default=None, help="Override example_idx (0-based).") + parser.add_argument("--sample", type=int, default=None, help="If the original run used --sample, set it here.") + parser.add_argument("--seed", type=int, default=42, help="Seed for --sample shuffling (must match original).") + + parser.add_argument("--model", type=str, default="qwen-8B", help="HF repo id (used when --model_path not set).") + parser.add_argument( + "--model_path", + type=str, + default="/opt/share/models/Qwen/Qwen3-8B/", + help="Local model path; overrides --model for loading (matches exp2 README examples).", + ) + parser.add_argument( + "--cuda", + type=str, + default="2,3,4,5,6,7", + help="CUDA selection (same semantics as exp2): '0' or '0,1,2'.", + ) + parser.add_argument("--cuda_num", type=int, default=0, help="Single-device index when --cuda not set.") + + parser.add_argument("--chunk_tokens", type=int, default=128) + parser.add_argument("--sink_chunk_tokens", type=int, default=32) + parser.add_argument("--n_hops", type=int, default=1) + + parser.add_argument( + "--inplace", + action="store_true", + help="Overwrite the trace npz in place (recommended so manifest.jsonl stays valid).", + ) + parser.add_argument("--no_backup", action="store_true", help="Disable .bak creation when using --inplace.") + parser.add_argument( + "--overwrite_backup", + action="store_true", + help="Allow replacing an existing .bak when using --inplace.", + ) + args = parser.parse_args() + + trace_npz = Path(args.trace_npz) + if not trace_npz.exists(): + raise SystemExit(f"Missing trace npz: {trace_npz}") + + example_idx = args.example_idx + if example_idx is None: + example_idx = _parse_example_idx_from_npz_name(trace_npz) + if example_idx is None: + raise SystemExit("Failed to infer --example_idx from trace filename; please pass --example_idx explicitly.") + + manifest_path = trace_npz.with_name("manifest.jsonl") + record = _load_manifest_record(manifest_path, example_idx=int(example_idx)) + + dataset_path = Path(args.dataset) + if not dataset_path.exists(): + raise SystemExit(f"Missing cached dataset JSONL: {dataset_path}") + examples = ds_utils.load_cached(dataset_path, sample=args.sample, seed=args.seed) + ex = _pick_example(examples, example_idx=int(example_idx), record=record) + + if ex.target is None: + raise SystemExit("Cached dataset example has target=None; this script requires cached targets (CoT+answer).") + prompt = ex.prompt + target = ex.target + + sink_span = tuple(ex.sink_span) if ex.sink_span else None + thinking_span = tuple(ex.thinking_span) if ex.thinking_span else None + + model_name = str(args.model_path or args.model).strip() + if not model_name: + raise SystemExit("Please set --model or --model_path.") + device = _resolve_device(args.cuda, args.cuda_num) + model, tokenizer = _load_model(model_name, device) + + attr = _run_ifr_attr( + str(args.attr_func), + model=model, + tokenizer=tokenizer, + prompt=prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(args.n_hops), + chunk_tokens=int(args.chunk_tokens), + sink_chunk_tokens=int(args.sink_chunk_tokens), + ) + vh = _extract_vh(attr) + + with np.load(trace_npz, allow_pickle=False) as old: + payload = {k: old[k] for k in old.files} + payload["vh"] = vh + + if args.inplace: + out_path = trace_npz + else: + out_path = trace_npz.with_name(trace_npz.stem + "_with_vh.npz") + + _save_npz( + out_path, + payload=payload, + inplace_src=trace_npz if args.inplace else None, + backup=not bool(args.no_backup), + overwrite_backup=bool(args.overwrite_backup), + ) + + print(f"Saved vh -> {out_path}") + print(f"vh shape: {vh.shape} (n_hops+1, prompt_len+gen_len)") + + +if __name__ == "__main__": + main() diff --git a/evaluations/attribution_recovery.py b/evaluations/attribution_recovery.py new file mode 100644 index 0000000000000000000000000000000000000000..7a390c56fc24b6198d51396caa9ec222b0e03e63 --- /dev/null +++ b/evaluations/attribution_recovery.py @@ -0,0 +1,490 @@ +import os +import sys + +# Ensure project root is importable regardless of CWD +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +import argparse +import csv +import json +import math +import random +import time +from itertools import islice +from pathlib import Path +from typing import List, Optional, Tuple + +import numpy as np +import torch +from tqdm import tqdm +from transformers import AutoModelForCausalLM, AutoTokenizer, utils + +import llm_attr +import llm_attr_eval +from exp.exp2 import dataset_utils as ds_utils + + +utils.logging.set_verbosity_error() + + +def _first_json_obj(path: Path) -> dict: + with path.open("r", encoding="utf-8") as f: + for line in f: + line = line.strip() + if line: + return json.loads(line) + return {} + + +def _load_ruler_examples(args) -> Tuple[str, List[ds_utils.CachedExample]]: + ds_arg = args.dataset + cache_dir = Path(args.data_root) + + # 1) If dataset points to an existing file, detect cache vs raw RULER. + p = Path(ds_arg) + if p.exists(): + obj = _first_json_obj(p) + if "prompt" in obj: + return p.stem, ds_utils.load_cached(p, sample=args.sample, seed=args.seed) + if "input" in obj and "needle_spans" in obj: + return p.stem, ds_utils.load_ruler(p, sample=args.sample, seed=args.seed) + raise SystemExit( + f"Unsupported JSONL schema for recovery_ruler: {p}. " + "Expected either exp2 cache (has 'prompt') or raw RULER JSONL (has 'input'+'needle_spans')." + ) + + # 2) Prefer exp2 cache under --data_root by dataset name. + cached = cache_dir / f"{ds_arg}.jsonl" + if cached.exists(): + return ds_arg, ds_utils.load_cached(cached, sample=args.sample, seed=args.seed) + + # 3) Fall back to raw RULER resolution by name. + resolved = ds_utils.dataset_from_name(ds_arg) + if resolved is None: + raise SystemExit(f"Could not resolve RULER dataset name '{ds_arg}'.") + return ds_arg, ds_utils.load_ruler(resolved, sample=args.sample, seed=args.seed) + + +def _resolve_indices_to_explain_token_span( + attr_result: llm_attr.LLMAttributionResult, indices_to_explain: list[int] | None +) -> list[int]: + if ( + isinstance(indices_to_explain, list) + and len(indices_to_explain) == 2 + and all(isinstance(x, int) and x >= 0 for x in indices_to_explain) + and indices_to_explain[0] <= indices_to_explain[1] + ): + return indices_to_explain + + gen_len = int(attr_result.attribution_matrix.shape[0]) + if gen_len <= 0: + return [0, 0] + + # Default: explain the full generation excluding the appended EOS token. + end_tok = max(0, gen_len - 2) + return [0, end_tok] + + +def run_attribution( + testing_dict, example: ds_utils.CachedExample, batch_size: int, target: Optional[str] +) -> tuple[List[torch.Tensor], dict | None]: + model = testing_dict["model"] + tokenizer = testing_dict["tokenizer"] + attr_func = testing_dict["attr_func"] + + if "IG" in attr_func: + llm_attributor = llm_attr.LLMGradientAttribtion(model, tokenizer) + attr = llm_attributor.calculate_IG_per_generation( + example.prompt, + 20, + tokenizer.eos_token_id, + batch_size=batch_size, + target=target, + ) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if "perturbation" in attr_func: + llm_attributor = llm_attr.LLMPerturbationAttribution(model, tokenizer) + if attr_func == "perturbation_all": + attr = llm_attributor.calculate_feature_ablation_sentences( + example.prompt, baseline=tokenizer.eos_token_id, measure="log_loss", target=target + ) + elif attr_func == "perturbation_CLP": + attr = llm_attributor.calculate_feature_ablation_sentences( + example.prompt, baseline=tokenizer.eos_token_id, measure="KL", target=target + ) + elif attr_func == "perturbation_REAGENT": + attr = llm_attributor.calculate_feature_ablation_sentences_mlm(example.prompt, target=target) + else: + raise ValueError(f"Unsupported perturbation attr_func {attr_func}") + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if "attention" in attr_func: + llm_attributor = llm_attr.LLMAttentionAttribution(model, tokenizer) + llm_attributor_ig = llm_attr.LLMGradientAttribtion(model, tokenizer) + attr = llm_attributor.calculate_attention_attribution(example.prompt, target=target) + if attr_func == "attention_I_G": + attr_b = llm_attributor_ig.calculate_IG_per_generation( + example.prompt, 20, tokenizer.eos_token_id, batch_size=batch_size, target=target + ) + attr.attribution_matrix = attr.attribution_matrix * attr_b.attribution_matrix + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "ifr_all_positions": + llm_attributor = llm_attr.LLMIFRAttribution(model, tokenizer) + attr = llm_attributor.calculate_ifr_for_all_positions(example.prompt, target=target) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "ifr_all_positions_output_only": + llm_attributor = llm_attr.LLMIFRAttribution(model, tokenizer) + sink_span = tuple(example.sink_span) if example.sink_span else None + attr = llm_attributor.calculate_ifr_for_all_positions_output_only( + example.prompt, + target=target, + sink_span=sink_span, + ) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "ifr_span": + llm_attributor = llm_attr.LLMIFRAttribution(model, tokenizer) + span = example.sink_span if example.sink_span else None + attr = llm_attributor.calculate_ifr_span(example.prompt, target=target, span=tuple(span) if span else None) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "ifr_multi_hop": + llm_attributor = llm_attr.LLMIFRAttribution(model, tokenizer) + attr = llm_attributor.calculate_ifr_multi_hop( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict.get("n_hops", 1), + ) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "ifr_in_all_gen": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionInAllGen(model, tokenizer) + attr = llm_attributor.calculate_ifr_in_all_gen( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict.get("n_hops", 1), + ) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "ifr_multi_hop_stop_words": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionImproved(model, tokenizer) + attr = llm_attributor.calculate_ifr_multi_hop_stop_words( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict.get("n_hops", 1), + ) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + extra = { + "keep_prompt_token_indices": ft_ifr_improve.keep_token_indices(list(attr.prompt_tokens)), + } + return list(attr.get_all_token_attrs(token_span)), extra + + if attr_func == "ifr_multi_hop_both": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionBoth(model, tokenizer) + attr = llm_attributor.calculate_ifr_multi_hop_both( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict.get("n_hops", 1), + ) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + extra = { + "keep_prompt_token_indices": ft_ifr_improve.keep_token_indices(list(attr.prompt_tokens)), + } + return list(attr.get_all_token_attrs(token_span)), extra + + if attr_func == "ifr_multi_hop_split_hop": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionSplitHop(model, tokenizer) + attr = llm_attributor.calculate_ifr_multi_hop_split_hop( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict.get("n_hops", 1), + ) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "basic": + llm_attributor = llm_attr.LLMBasicAttribution(model, tokenizer) + attr = llm_attributor.calculate_basic_attribution(example.prompt, target=target) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "attnlrp": + llm_attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + sink_span = getattr(example, "sink_span", None) + thinking_span = getattr(example, "thinking_span", None) + attr = llm_attributor.calculate_attnlrp_ft_hop0( + example.prompt, + target=target, + sink_span=tuple(sink_span) if sink_span else None, + thinking_span=tuple(thinking_span) if thinking_span else None, + ) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "attnlrp_aggregated": + llm_attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + attr = llm_attributor.calculate_attnlrp_aggregated(example.prompt, target=target) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + if attr_func == "attnlrp_aggregated_multi_hop": + llm_attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + attr = llm_attributor.calculate_attnlrp_aggregated_multi_hop( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict.get("n_hops", 1), + ) + token_span = _resolve_indices_to_explain_token_span(attr, example.indices_to_explain) + return list(attr.get_all_token_attrs(token_span)), None + + raise ValueError(f"Unsupported attribution function '{attr_func}'.") + + +def evaluate_dataset_recovery_ruler(testing_dict, dataset_name: str, examples: List[ds_utils.CachedExample]) -> Tuple[np.ndarray, np.ndarray, float, int, int]: + tokenizer = testing_dict["tokenizer"] + llm_evaluator = llm_attr_eval.LLMAttributionEvaluator(testing_dict["model"], tokenizer) + + results: List[np.ndarray] = [] + durations: List[float] = [] + skipped = 0 + + num_examples = testing_dict["num_examples"] + total = min(len(examples), num_examples) + iterator = islice(examples, total) + + description = f"Recovery@10pct {testing_dict['model_name']} {dataset_name} {testing_dict['attr_func']}" + for ex in tqdm(iterator, desc=description, total=total): + needle_spans = (ex.metadata or {}).get("needle_spans") + if not isinstance(needle_spans, list) or not needle_spans: + raise SystemExit( + "recovery_ruler only supports RULER examples with metadata.needle_spans; " + f"dataset={dataset_name} has missing/empty needle_spans." + ) + + gold_prompt = ds_utils.ruler_gold_prompt_token_indices(ex, tokenizer) + if not gold_prompt: + skipped += 1 + continue + + # Batch size is set based on the max_input_len (same policy as faithfulness). + target = ex.target + if target is None: + generation, full_output = llm_evaluator.response(ex.prompt) + target = generation + response_len = len(tokenizer(full_output).input_ids) + else: + response_len = len(tokenizer(llm_evaluator.format_prompt(" " + ex.prompt) + target).input_ids) + batch_size = max(1, math.floor((testing_dict["max_input_len"] - 100) / max(1, response_len))) + + sample_start = time.perf_counter() + attr_list, extra = run_attribution(testing_dict, ex, batch_size, target) + durations.append(time.perf_counter() - sample_start) + + seq_attr = attr_list[0] + prompt_len = int(seq_attr.shape[1] - seq_attr.shape[0]) # cols=(P+G), rows=G + if prompt_len <= 0: + skipped += 1 + continue + + if testing_dict["attr_func"] in ("ifr_multi_hop_stop_words", "ifr_multi_hop_both") and extra is not None: + import ft_ifr_improve + + keep_prompt_token_indices = extra.get("keep_prompt_token_indices") or [] + gold_filtered = [idx for idx in gold_prompt if int(idx) in set(int(x) for x in keep_prompt_token_indices)] + if not gold_filtered: + skipped += 1 + continue + scores = [ + ft_ifr_improve.evaluate_attr_recovery_skip_tokens( + attr[:, :prompt_len], + keep_prompt_token_indices=keep_prompt_token_indices, + gold_prompt_token_indices=gold_prompt, + top_fraction=0.1, + ) + for attr in attr_list + ] + else: + scores = [ + llm_evaluator.evaluate_attr_recovery( + attr, + prompt_len=prompt_len, + gold_prompt_token_indices=gold_prompt, + top_fraction=0.1, + ) + for attr in attr_list + ] + results.append(np.asarray(scores, dtype=np.float64)) + + scores = np.stack(results, axis=0) if results else np.zeros((0, 3), dtype=np.float64) + used = int(scores.shape[0]) + mean = scores.mean(0) if used else np.full((3,), np.nan, dtype=np.float64) + std = scores.std(0) if used else np.full((3,), np.nan, dtype=np.float64) + avg_time = float(np.mean(durations)) if durations else 0.0 + return mean, std, avg_time, used, int(skipped) + + +def load_model(model_name: str, device: str) -> Tuple[AutoModelForCausalLM, AutoTokenizer]: + seed = 42 + random.seed(seed) + np.random.seed(seed) + torch.manual_seed(seed) + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) + + if device == "auto": + model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map="auto", + attn_implementation="eager", + torch_dtype=torch.float16, + ) + elif isinstance(device, str) and device.startswith("cuda:"): + try: + gpu_idx = int(device.split(":")[1]) + except Exception: + gpu_idx = 0 + model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map={"": gpu_idx}, + attn_implementation="eager", + torch_dtype=torch.float16, + ) + else: + model = AutoModelForCausalLM.from_pretrained( + model_name, + attn_implementation="eager", + torch_dtype=torch.float16, + ) + model.eval() + tokenizer = AutoTokenizer.from_pretrained(model_name) + tokenizer.pad_token = tokenizer.eos_token + return model, tokenizer + + +def main(args) -> None: + if args.cuda is not None and isinstance(args.cuda, str) and "," in args.cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = args.cuda + device = "auto" + elif args.cuda is not None and isinstance(args.cuda, str) and args.cuda.strip() != "": + try: + idx = int(args.cuda) + except Exception: + idx = 0 + device = f"cuda:{idx}" if torch.cuda.is_available() else "cpu" + else: + device = f"cuda:{args.cuda_num}" if torch.cuda.is_available() else "cpu" + + if args.model == "llama-1B": + model_name = "meta-llama/Llama-3.2-1B-Instruct" + max_input_len = 5500 + elif args.model == "llama-3B": + model_name = "meta-llama/Llama-3.2-3B-Instruct" + max_input_len = 4800 + elif args.model == "llama-8B": + model_name = "meta-llama/Llama-3.1-8B-Instruct" + max_input_len = 3500 + elif args.model == "qwen-1.7B": + model_name = "Qwen/Qwen3-1.7B" + max_input_len = 5500 + elif args.model == "qwen-4B": + model_name = "Qwen/Qwen3-4B-Instruct-2507" + max_input_len = 3500 + elif args.model == "qwen-8B": + model_name = "Qwen/Qwen3-8B" + max_input_len = 3000 + elif args.model == "qwen-32B": + model_name = "Qwen/Qwen3-32B" + max_input_len = 1500 + elif args.model == "gemma-12B": + model_name = "gemma/gemma-3-12b-it" + max_input_len = 1500 + elif args.model == "gemma-27B": + model_name = "gemma/gemma-3-27b-it" + max_input_len = 2000 + else: + model_name = args.model_path if args.model_path is not None else args.model + max_input_len = 2000 + + model, tokenizer = load_model(model_name if args.model_path is None else args.model_path, device) + + dataset_name, examples = _load_ruler_examples(args) + + testing_dict = { + "model": model, + "model_name": args.model, + "tokenizer": tokenizer, + "dataset_name": dataset_name, + "attr_func": args.attr_func, + "num_examples": args.num_examples, + "max_input_len": max_input_len, + "n_hops": args.n_hops, + } + + mean, std, avg_time, used, skipped = evaluate_dataset_recovery_ruler(testing_dict, dataset_name, examples) + + out_dir = Path("./test_results") / "attribution_recovery" / dataset_name / args.model + out_dir.mkdir(parents=True, exist_ok=True) + file_name = f"{args.attr_func}_{args.num_examples}_examples.csv" + with open(out_dir / file_name, "w", newline="") as f: + writer = csv.writer(f) + writer.writerow(["Method", "Recovery@10pct"]) + writer.writerow(["Seq Attr Recovery Mean", mean[0]]) + writer.writerow(["Row Attr Recovery Mean", mean[1]]) + writer.writerow(["Recursive Attr Recovery Mean", mean[2]]) + writer.writerow(["Seq Attr Recovery Std", std[0]]) + writer.writerow(["Row Attr Recovery Std", std[1]]) + writer.writerow(["Recursive Attr Recovery Std", std[2]]) + writer.writerow(["Examples Used", used]) + writer.writerow(["Examples Skipped", skipped]) + writer.writerow(["Avg Sample Time (s)", avg_time]) + + print(f"[{dataset_name}] {args.attr_func} -> {out_dir/file_name} (used={used} skipped={skipped} avg {avg_time:.2f}s)") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser("RULER-only token-level attribution recovery evaluation (Recall@10pct).") + parser.add_argument("--num_examples", type=int, default=100, help="How many examples to evaluate.") + parser.add_argument("--sample", type=int, default=None, help="Optional subsample before num_examples.") + parser.add_argument("--seed", type=int, default=42) + parser.add_argument("--model", type=str, default="qwen-8B") + parser.add_argument("--model_path", type=str, default=None, help="Optional local model path to load.") + parser.add_argument("--attr_func", type=str, default="ifr_multi_hop") + parser.add_argument("--cuda_num", type=int, default=0) + parser.add_argument("--cuda", type=str, default=None) + parser.add_argument("--dataset", type=str, required=True, help="RULER dataset name or JSONL path (raw or exp2 cache).") + parser.add_argument("--data_root", type=str, default="exp/exp2/data", help="Cache directory to search by dataset name.") + parser.add_argument("--n_hops", type=int, default=3) + + args, _ = parser.parse_known_args() + main(args) diff --git a/evaluations/attribution_recovery.sh b/evaluations/attribution_recovery.sh new file mode 100644 index 0000000000000000000000000000000000000000..67fc11247a30223ea8cca8515e022a935f4c43bc --- /dev/null +++ b/evaluations/attribution_recovery.sh @@ -0,0 +1,18 @@ +# RULER-only token-level recovery (Recall@10pct) examples. +# +# Dataset can be: +# - a RULER name (hotpotqa_long / niah_* / vt_*) resolved under data/ruler_multihop//.../validation.jsonl +# - a raw RULER JSONL path +# - an exp2 cache JSONL path (must contain metadata.needle_spans) + +# Example: evaluate on exp2 cache +# CUDA_VISIBLE_DEVICES=0 python3 evaluations/attribution_recovery.py \ +# --model qwen-8B --model_path /opt/share/models/Qwen/Qwen3-8B/ \ +# --cuda 0 --num_examples 50 --attr_func ifr_multi_hop \ +# --dataset exp/exp2/data/hotpotqa.jsonl + +# Example: evaluate on raw RULER JSONL +# CUDA_VISIBLE_DEVICES=0 python3 evaluations/attribution_recovery.py \ +# --model qwen-8B --model_path /opt/share/models/Qwen/Qwen3-8B/ \ +# --cuda 0 --num_examples 50 --attr_func ifr_multi_hop \ +# --dataset data/ruler_multihop/4096/hotpotqa_long/validation.jsonl diff --git a/evaluations/faithfulness.py b/evaluations/faithfulness.py new file mode 100644 index 0000000000000000000000000000000000000000..f44c182efde3b7be4b49d47d53145d52f9a68dd9 --- /dev/null +++ b/evaluations/faithfulness.py @@ -0,0 +1,491 @@ +import os +import sys +# Ensure project root is importable regardless of CWD +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from transformers import AutoModelForCausalLM, BitsAndBytesConfig, AutoTokenizer +import torch +import numpy as np +from transformers import utils +import math +from tqdm import tqdm +import random +import argparse +import csv +from itertools import islice +from typing import Tuple +from huggingface_hub import login + +from attribution_datasets import ( + AttributionDataset, + FactsAttributionDataset, + MathAttributionDataset, + MoreHopQAAttributionDataset, +) + +utils.logging.set_verbosity_error() # Suppress standard warnings + +import llm_attr +import llm_attr_eval + + +def _resolve_indices_to_explain_token_span( + attr_result: llm_attr.LLMAttributionResult, indices_to_explain: list[int] | None +) -> list[int]: + if ( + isinstance(indices_to_explain, list) + and len(indices_to_explain) == 2 + and all(isinstance(x, int) and x >= 0 for x in indices_to_explain) + and indices_to_explain[0] <= indices_to_explain[1] + ): + return indices_to_explain + + gen_len = int(attr_result.attribution_matrix.shape[0]) + if gen_len <= 0: + return [0, 0] + + # Default: explain the full generation excluding the appended EOS token. + end_tok = max(0, gen_len - 2) + return [0, end_tok] + + +def run_attribution(testing_dict, prompt, batch_size, indices_to_explain = [1], target = None) -> tuple[list[torch.Tensor], dict | None]: + model = testing_dict["model"] + tokenizer = testing_dict["tokenizer"] + + # Now we create an attribution for the full response + if "IG" in testing_dict["attr_func"]: + llm_attributor = llm_attr.LLMGradientAttribtion(model, tokenizer) + + if testing_dict["attr_func"] == "IG": + attr = llm_attributor.calculate_IG_per_generation(prompt, 20, tokenizer.eos_token_id, batch_size = batch_size, target = target) + + token_span = _resolve_indices_to_explain_token_span(attr, indices_to_explain) + attributions = list(attr.get_all_token_attrs(token_span)) + + elif "perturbation" in testing_dict["attr_func"]: + llm_attributor = llm_attr.LLMPerturbationAttribution(model, tokenizer) + + if testing_dict["attr_func"] == "perturbation_all": + attr = llm_attributor.calculate_feature_ablation_sentences(prompt, baseline = tokenizer.eos_token_id, measure="log_loss", target = target) + elif testing_dict["attr_func"] == "perturbation_CLP": + attr = llm_attributor.calculate_feature_ablation_sentences(prompt, baseline = tokenizer.eos_token_id, measure="KL", target = target) + elif testing_dict["attr_func"] == "perturbation_REAGENT": + attr = llm_attributor.calculate_feature_ablation_sentences_mlm(prompt, target = target) + + token_span = _resolve_indices_to_explain_token_span(attr, indices_to_explain) + attributions = list(attr.get_all_token_attrs(token_span)) + + elif "attention" in testing_dict["attr_func"]: + llm_attributor = llm_attr.LLMAttentionAttribution(model, tokenizer) + llm_attributor_ig = llm_attr.LLMGradientAttribtion(model, tokenizer) + + if testing_dict["attr_func"] == "attention_I_G": + attr = llm_attributor.calculate_attention_attribution(prompt, target = target) + attr_b = llm_attributor_ig.calculate_IG_per_generation(prompt, 20, tokenizer.eos_token_id, batch_size = batch_size, target = target) + attr.attribution_matrix = attr.attribution_matrix * attr_b.attribution_matrix + + token_span = _resolve_indices_to_explain_token_span(attr, indices_to_explain) + attributions = list(attr.get_all_token_attrs(token_span)) + + elif "ifr" in testing_dict["attr_func"].lower(): + llm_attributor = llm_attr.LLMIFRAttribution(model, tokenizer) + attr_func = testing_dict["attr_func"].lower() + renorm_threshold = testing_dict.get("renorm_threshold") + + if attr_func == "ifr_all_positions": + attr = llm_attributor.calculate_ifr_for_all_positions(prompt, target=target, renorm_threshold=renorm_threshold) + elif attr_func == "ifr_all_positions_output_only": + attr = llm_attributor.calculate_ifr_for_all_positions_output_only( + prompt, + target=target, + sink_span=tuple(testing_dict.get("sink_span")) if testing_dict.get("sink_span") is not None else None, + renorm_threshold=renorm_threshold, + ) + elif attr_func == "ifr_span": + span = testing_dict.get("sink_span") + attr = llm_attributor.calculate_ifr_span( + prompt, + target=target, + span=tuple(span) if span is not None else None, + renorm_threshold=renorm_threshold, + ) + elif attr_func == "ifr_multi_hop": + attr = llm_attributor.calculate_ifr_multi_hop( + prompt, + target=target, + sink_span=tuple(testing_dict.get("sink_span")) if testing_dict.get("sink_span") is not None else None, + thinking_span=tuple(testing_dict.get("thinking_span")) if testing_dict.get("thinking_span") is not None else None, + n_hops=testing_dict.get("n_hops", 1), + renorm_threshold=renorm_threshold, + observation_mask=testing_dict.get("observation_mask"), + ) + elif attr_func == "ifr_in_all_gen": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionInAllGen(model, tokenizer) + attr = llm_attributor.calculate_ifr_in_all_gen( + prompt, + target=target, + sink_span=tuple(testing_dict.get("sink_span")) if testing_dict.get("sink_span") is not None else None, + thinking_span=tuple(testing_dict.get("thinking_span")) if testing_dict.get("thinking_span") is not None else None, + n_hops=testing_dict.get("n_hops", 1), + renorm_threshold=renorm_threshold, + observation_mask=testing_dict.get("observation_mask"), + ) + elif attr_func == "ifr_multi_hop_stop_words": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionImproved(model, tokenizer) + attr = llm_attributor.calculate_ifr_multi_hop_stop_words( + prompt, + target=target, + sink_span=tuple(testing_dict.get("sink_span")) if testing_dict.get("sink_span") is not None else None, + thinking_span=tuple(testing_dict.get("thinking_span")) if testing_dict.get("thinking_span") is not None else None, + n_hops=testing_dict.get("n_hops", 1), + renorm_threshold=renorm_threshold, + observation_mask=testing_dict.get("observation_mask"), + ) + elif attr_func == "ifr_multi_hop_both": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionBoth(model, tokenizer) + attr = llm_attributor.calculate_ifr_multi_hop_both( + prompt, + target=target, + sink_span=tuple(testing_dict.get("sink_span")) if testing_dict.get("sink_span") is not None else None, + thinking_span=tuple(testing_dict.get("thinking_span")) if testing_dict.get("thinking_span") is not None else None, + n_hops=testing_dict.get("n_hops", 1), + renorm_threshold=renorm_threshold, + observation_mask=testing_dict.get("observation_mask"), + ) + elif attr_func == "ifr_multi_hop_split_hop": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionSplitHop(model, tokenizer) + attr = llm_attributor.calculate_ifr_multi_hop_split_hop( + prompt, + target=target, + sink_span=tuple(testing_dict.get("sink_span")) if testing_dict.get("sink_span") is not None else None, + thinking_span=tuple(testing_dict.get("thinking_span")) if testing_dict.get("thinking_span") is not None else None, + n_hops=testing_dict.get("n_hops", 1), + renorm_threshold=renorm_threshold, + observation_mask=testing_dict.get("observation_mask"), + ) + else: + raise ValueError(f"Unsupported IFR attribution function '{testing_dict['attr_func']}'.") + + token_span = _resolve_indices_to_explain_token_span(attr, indices_to_explain) + attributions = list(attr.get_all_token_attrs(token_span)) + + elif "basic" in testing_dict["attr_func"]: + llm_attributor = llm_attr.LLMBasicAttribution(model, tokenizer) + attr = llm_attributor.calculate_basic_attribution(prompt, target = target) + token_span = _resolve_indices_to_explain_token_span(attr, indices_to_explain) + attributions = list(attr.get_all_token_attrs(token_span)) + + elif testing_dict["attr_func"] == "attnlrp": + llm_attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + attr = llm_attributor.calculate_attnlrp_ft_hop0(prompt, target=target) + token_span = _resolve_indices_to_explain_token_span(attr, indices_to_explain) + attributions = list(attr.get_all_token_attrs(token_span)) + + elif testing_dict["attr_func"] == "attnlrp_aggregated": + llm_attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + attr = llm_attributor.calculate_attnlrp_aggregated(prompt, target=target) + token_span = _resolve_indices_to_explain_token_span(attr, indices_to_explain) + attributions = list(attr.get_all_token_attrs(token_span)) + + elif testing_dict["attr_func"] == "attnlrp_aggregated_multi_hop": + llm_attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + attr = llm_attributor.calculate_attnlrp_aggregated_multi_hop( + prompt, + target=target, + sink_span=tuple(testing_dict.get("sink_span")) if testing_dict.get("sink_span") is not None else None, + thinking_span=tuple(testing_dict.get("thinking_span")) if testing_dict.get("thinking_span") is not None else None, + n_hops=testing_dict.get("n_hops", 1), + ) + token_span = _resolve_indices_to_explain_token_span(attr, indices_to_explain) + attributions = list(attr.get_all_token_attrs(token_span)) + + else: + raise ValueError(f"Unsupported attribution function '{testing_dict['attr_func']}'.") + + extra = None + if testing_dict["attr_func"].lower() in ("ifr_multi_hop_stop_words", "ifr_multi_hop_both"): + import ft_ifr_improve + + extra = { + "keep_prompt_token_indices": ft_ifr_improve.keep_token_indices(list(attr.prompt_tokens)), + "user_prompt_indices": list(getattr(llm_attributor, "user_prompt_indices", []) or []), + } + + return attributions, extra + +def faithfulness_test(testing_dict, llm_evaluator, prompt, indices_to_explain, target = None) -> np.ndarray[float]: + tokenizer = testing_dict["tokenizer"] + faithfulness_k = int(testing_dict.get("faithfulness_k", 20)) + + scores = [] + + # batch size is set based on the max_input_len in main(). Currently set to fully fill a 196GB GPU. + if target is None: + generation, full_output = llm_evaluator.response(prompt) + batch_size = math.floor((testing_dict["max_input_len"] - 100) / len(tokenizer(full_output).input_ids)) + else: + generation = target + batch_size = math.floor( + (testing_dict["max_input_len"] - 100) + / len(tokenizer(llm_evaluator.format_prompt(" " + prompt) + generation).input_ids) + ) + + # We run an attribution on the input + # A list of attribution tensors will be returned and scored individually. + attr_list, extra = run_attribution(testing_dict, prompt, batch_size, indices_to_explain = indices_to_explain, target = target) + + seq_attr = attr_list[0] + prompt_len = int(seq_attr.shape[1] - seq_attr.shape[0]) # cols=(P+G), rows=G + + for i in range(len(attr_list)): + attr = attr_list[i][:, :prompt_len] + if testing_dict["attr_func"].lower() in ("ifr_multi_hop_stop_words", "ifr_multi_hop_both") and extra is not None: + import ft_ifr_improve + + scores.append( + ft_ifr_improve.faithfulness_test_skip_tokens( + llm_evaluator, + attr, + prompt, + generation, + keep_prompt_token_indices=extra.get("keep_prompt_token_indices") or [], + user_prompt_indices=extra.get("user_prompt_indices"), + k=faithfulness_k, + ) + ) + else: + scores.append(llm_evaluator.faithfulness_test(attr, prompt, generation, k=faithfulness_k)) # [3 scores] + + return np.array(scores) + +def clean_trailing_space(text) -> str: + if text[-1] == ' ': + return text[:-1] + else: + return text + +def evaluate_attribution(testing_dict) -> None: + model = testing_dict["model"] + tokenizer = testing_dict["tokenizer"] + + llm_evaluator = llm_attr_eval.LLMAttributionEvaluator(model, tokenizer) + + scores = [] + + description = "Faithfulness " + testing_dict["model_name"] + " " + testing_dict["dataset_name"] + " " + testing_dict["attr_func"] + + dataset: AttributionDataset = testing_dict["dataset"] + num_examples = testing_dict["num_examples"] + total = min(len(dataset), num_examples) if hasattr(dataset, "__len__") else num_examples + example_iterator = islice(dataset, num_examples) + + for example in tqdm(example_iterator, desc=description, total=total): + indices_to_explain = example.indices_to_explain if example.indices_to_explain is not None else [-2] + scores.append( + faithfulness_test( + testing_dict, + llm_evaluator, + example.prompt, + indices_to_explain=indices_to_explain, + target=example.target, + ) + ) + + scores = np.array(scores) # [num_examples, num_attrs, 3 scores] + scores_mean = scores.mean(0) # [num_attrs, 3 scores] + scores_var = scores.std(0) # [num_attrs, 3 scores] + + # make the test folder if it doesn't exist + folder = "./test_results/faithfulness/" + testing_dict["dataset_name"] + "/" + testing_dict["model_name"] + "/" + if not os.path.exists(folder): + os.makedirs(folder) + + # save all data + file_name = testing_dict["attr_func"] + "_" + str(testing_dict["num_examples"]) + "_examples" + with open(folder + file_name + ".csv", 'w') as f: + write = csv.writer(f) + + write.writerow(["Method", "RISE", "MAS", "RISE + AP"]) + + write.writerow(["Seq Attr Scores Mean"] + scores_mean[0].tolist()) + write.writerow(["Row Attr Scores Mean"] + scores_mean[1].tolist()) + write.writerow(["Recursive Attr Scores Mean"] + scores_mean[2].tolist()) + + write.writerow(["Seq Attr Scores Var"] + scores_var[0].tolist()) + write.writerow(["Row Attr Scores Var"] + scores_var[1].tolist()) + write.writerow(["Recursive Attr Scores Var"] + scores_var[2].tolist()) + + return + +def load_model(model_name, device) -> Tuple[AutoModelForCausalLM, AutoTokenizer]: + seed = 42 + random.seed(seed) + np.random.seed(seed) + torch.manual_seed(seed) + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) # if multi-GPU + + # Respect three modes: + # - device == 'auto' -> multi-GPU sharding across all visible devices + # - device startswith('cuda:IDX') -> place entire model on a single GPU IDX (relative to visible devices) + # - device == 'cpu' -> CPU + if device == "auto": + model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map="auto", + attn_implementation="eager", + torch_dtype=torch.float16, + ) + elif isinstance(device, str) and device.startswith("cuda:"): + try: + gpu_idx = int(device.split(":")[1]) + except Exception: + gpu_idx = 0 + model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map={"": gpu_idx}, + attn_implementation="eager", + torch_dtype=torch.float16, + ) + else: + model = AutoModelForCausalLM.from_pretrained( + model_name, + attn_implementation="eager", + torch_dtype=torch.float16, + ) + model.eval() + tokenizer = AutoTokenizer.from_pretrained(model_name) + + # Needed for LLaMA tokenizer + tokenizer.pad_token = tokenizer.eos_token + + return model, tokenizer + +def main(args) -> None: + # login(token = "") + + # Device selection policy (mirrors attribution_recovery): + # - If --cuda is a comma-separated list (e.g. "0,1"), set visibility to that list and shard with device_map='auto'. + # - If --cuda is a single index (e.g. "0"), do NOT override CUDA_VISIBLE_DEVICES; place model on cuda:{index}. + # - Else (no --cuda), use --cuda_num as single-device index relative to current visibility. + if args.cuda is not None and isinstance(args.cuda, str) and "," in args.cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = args.cuda + device = "auto" + elif args.cuda is not None and isinstance(args.cuda, str) and args.cuda.strip() != "": + try: + idx = int(args.cuda) + except Exception: + idx = 0 + device = f"cuda:{idx}" if torch.cuda.is_available() else "cpu" + else: + device = f"cuda:{args.cuda_num}" if torch.cuda.is_available() else "cpu" + + # set up model + if args.model == "llama-1B": + model_name = "meta-llama/Llama-3.2-1B-Instruct" + max_input_len = 5500 + elif args.model == "llama-3B": + model_name = "meta-llama/Llama-3.2-3B-Instruct" + max_input_len = 4800 + elif args.model == "llama-8B": + model_name = "meta-llama/Llama-3.1-8B-Instruct" + max_input_len = 3500 + elif args.model == "qwen-1.7B": + model_name = "Qwen/Qwen3-1.7B" + max_input_len = 5500 + elif args.model == "qwen-4B": + model_name = "Qwen/Qwen3-4B-Instruct-2507" + max_input_len = 3500 + elif args.model == "qwen-8B": + model_name = "Qwen/Qwen3-8B" + max_input_len = 3000 + elif args.model == "qwen-32B": + model_name = "Qwen/Qwen3-32B" + max_input_len = 1500 + elif args.model == "gemma-12B": + model_name = "gemma/gemma-3-12b-it" + max_input_len = 1500 + elif args.model == "gemma-27B": + model_name = "gemma/gemma-3-27b-it" + max_input_len = 2000 + else: + model_name = args.model_path if args.model_path is not None else args.model + max_input_len = 2000 + + model, tokenizer = load_model(model_name if args.model_path is None else args.model_path, device) + + dataset_registry = { + "math": lambda: MathAttributionDataset("./data/math_mine.json", tokenizer), + "facts": lambda: FactsAttributionDataset("./data/10000_facts_9_choose_3.json"), + "morehopqa": lambda: MoreHopQAAttributionDataset("./data/with_human_verification.json"), + } + dataset_loader = dataset_registry.get(args.dataset) + if dataset_loader is None: + print("You have not specified an acceptable dataset. Exiting.") + exit() + dataset = dataset_loader() + + testing_dict = { + "model" : model, + "model_name": args.model, + "tokenizer" : tokenizer, + "dataset" : dataset, + "dataset_name" : args.dataset, + "max_input_len": max_input_len, + "attr_func": args.attr_func, + "num_examples": args.num_examples, + "device": device, + "faithfulness_k": args.faithfulness_k, + } + + # call the test function + evaluate_attribution(testing_dict) + + return + +if __name__ == "__main__": + parser = argparse.ArgumentParser('') + parser.add_argument('--num_examples', + type = int, default = 100, + help='How many dataset examples to test with.') + parser.add_argument('--model', + type = str, + default = "llama", + help='Model to use: llama or qwen') + parser.add_argument('--model_path', + type=str, default=None, + help='Optional local model path to load (overrides model repo id only).') + parser.add_argument('--attr_func', + type = str, + default = "IG", + help="attr to use: \ + grad, IG, IG_captum, contextcite, attention, rollout, perturbation \ + ") + parser.add_argument('--cuda_num', + type=int, default = 0, + help='The number of the GPU you want to use.') + parser.add_argument('--cuda', + type=str, default=None, + help='GPU selection: use comma-separated ids for multi-GPU sharding (e.g. "0,1"); use a single index for one GPU relative to current CUDA_VISIBLE_DEVICES (e.g. "0").') + parser.add_argument('--dataset', + type = str, default = "math", + help = 'The dataset to evaluate on: math, facts, or morehopqa') + parser.add_argument( + "--faithfulness_k", + type=int, + default=20, + help="Total perturbation steps k for MAS/RISE (each step perturbs ~1/k of prompt tokens).", + ) + + args, unparsed = parser.parse_known_args() + + main(args) diff --git a/evaluations/faithfulness.sh b/evaluations/faithfulness.sh new file mode 100755 index 0000000000000000000000000000000000000000..21e0dc6a36a07f7ad94c25a5a0654b08b5f5d77e --- /dev/null +++ b/evaluations/faithfulness.sh @@ -0,0 +1,80 @@ +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func IG --dataset facts +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func IG --dataset facts +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func IG --dataset facts +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func IG --dataset facts + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset facts +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset facts +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset facts +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset facts + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset facts +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset facts +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset facts +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset facts + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset facts +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset facts +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset facts +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset facts + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset facts +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset facts +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset facts +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset facts + + + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func IG --dataset math +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func IG --dataset math +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func IG --dataset math +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func IG --dataset math + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset math +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset math +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset math +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset math + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset math +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset math +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset math +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset math + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset math +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset math +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset math +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset math + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset math +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset math +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset math +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset math + + + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func IG --dataset morehopqa +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func IG --dataset morehopqa +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func IG --dataset morehopqa +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func IG --dataset morehopqa + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset morehopqa +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset morehopqa +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset morehopqa +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func attention_I_G --dataset morehopqa + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset morehopqa +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset morehopqa +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset morehopqa +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_CLP --dataset morehopqa + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset morehopqa +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset morehopqa +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset morehopqa +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_REAGENT --dataset morehopqa + +# python3 faithfulness.py --model llama-3B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset morehopqa +# python3 faithfulness.py --model llama-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset morehopqa +# python3 faithfulness.py --model qwen-4B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset morehopqa +# python3 faithfulness.py --model qwen-8B --cuda_num 0 --num_examples 500 --attr_func perturbation_all --dataset morehopqa + +CUDA_VISIBLE_DEVICES=4,6 python3 evaluations/faithfulness.py --model qwen-8B --model_path /opt/share/models/Qwen/Qwen3-8B/ --cuda '0,1' --num_examples 50 --attr_func IG --dataset math diff --git a/example.ipynb b/example.ipynb new file mode 100755 index 0000000000000000000000000000000000000000..ab245476dd1b3631a72fa8696f2d92ada6815151 --- /dev/null +++ b/example.ipynb @@ -0,0 +1,520 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from transformers import AutoModelForCausalLM, PreTrainedTokenizerFast, BitsAndBytesConfig, AutoTokenizer\n", + "import torch\n", + "from matplotlib import pyplot as plt\n", + "import numpy as np\n", + "from transformers import utils\n", + "import llm_attr\n", + "import llm_attr_eval\n", + "import math\n", + "import random\n", + "from datasets import load_dataset\n", + "from evaluate import load\n", + "import json\n", + "\n", + "utils.logging.set_verbosity_error() # Suppress standard warnings\n", + "\n", + "def load_model(model_name):\n", + " seed = 42\n", + " random.seed(seed)\n", + " np.random.seed(seed)\n", + " torch.manual_seed(seed)\n", + " torch.cuda.manual_seed(seed)\n", + " torch.cuda.manual_seed_all(seed) # if multi-GPU\n", + "\n", + " model = AutoModelForCausalLM.from_pretrained(\n", + " model_name,\n", + " device_map=\"cuda\", # dispatch efficiently the model on the available ressources\n", + " attn_implementation=\"eager\",\n", + " torch_dtype=torch.float16\n", + " )\n", + " model.eval()\n", + " tokenizer = AutoTokenizer.from_pretrained(model_name, token=True)\n", + "\n", + " # Needed for LLaMA tokenizer\n", + " tokenizer.pad_token = tokenizer.eos_token\n", + "\n", + " return model, tokenizer\n", + "\n", + "model_name = \"meta-llama/Llama-3.2-1B-Instruct\" \n", + "mem_limit = 1400\n", + "model, tokenizer = load_model(model_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "DEFAULT_PROMPT_TEMPLATE = \"Context:{context}\\n\\n\\nQuery: {query}\"\n", + "\n", + "def model_forward(prompt, model, tokenizer, new_generations = 512, print_response = True):\n", + " modified_prompt = DEFAULT_PROMPT_TEMPLATE.format(context = \" \" + prompt, query = \"\")\n", + " formatted_prompt = [{\"role\": \"user\", \"content\": modified_prompt}]\n", + " formatted_prompt = tokenizer.apply_chat_template(\n", + " formatted_prompt,\n", + " tokenize=False,\n", + " add_generation_prompt=True,\n", + " enable_thinking=False # Switches between thinking and non-thinking modes. Default is True.\n", + " )\n", + "\n", + " model_input = tokenizer(formatted_prompt, return_tensors=\"pt\", add_special_tokens=False).to(\"cuda\")\n", + "\n", + " with torch.no_grad():\n", + " # outputs = model.generate(model_input.input_ids, do_sample = False, temperature = 1.0, top_k = 0, top_p = 1.0, num_beams = 1, repetition_penalty = 1.0, max_new_tokens = new_generations)[0]\n", + " outputs = model.generate(model_input.input_ids, do_sample = False, max_new_tokens = new_generations)[0]\n", + " \n", + " # Get only the generated tokens (excluding the prompt)\n", + " generated_ids = outputs[model_input.input_ids.shape[1]:] # Slice off the prompt\n", + " # print(tokenizer.convert_ids_to_tokens(generated_ids))\n", + " generated_text = tokenizer.decode(generated_ids, skip_special_tokens=True)\n", + " if print_response:\n", + " print(tokenizer.decode(outputs))\n", + " \n", + " return generated_text\n", + "\n", + "def preprocess_example(example) -> str:\n", + " \"\"\"\n", + " Converts HotpotQA context to a single string for compatibility with SQuAD.\n", + " \"\"\"\n", + " # If it's already a string (SQuAD), leave it alone\n", + " if isinstance(example[\"context\"], str):\n", + " return example\n", + " \n", + " # Otherwise, flatten HotpotQA context\n", + " flattened_context = \"\"\n", + " for title, sentences in zip(example[\"context\"][\"title\"], example[\"context\"][\"sentences\"]):\n", + " flattened_context += f\"{title}\\n\"\n", + " flattened_context += \"\\n\".join(sentences) + \"\\n\\n\"\n", + " \n", + " example[\"context\"] = flattened_context.strip()\n", + " return example\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "llm_evaluator = llm_attr_eval.LLMAttributionEvaluator(model, tokenizer)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# # https://huggingface.co/datasets/alabnii/morehopqa\n", + "\n", + "# with open(\"data/with_human_verification.json\", \"r\") as f:\n", + "# data = json.load(f)\n", + "\n", + "# index = 0\n", + "# context = \"\"\n", + "# question = data[index][\"question\"]\n", + "# answer = data[index][\"answer\"]\n", + "# context_len = len(data[index][\"context\"])\n", + "# for i, item in enumerate(data[index][\"context\"]):\n", + "# context += \"\".join(item[1])\n", + "# if i != context_len - 1:\n", + "# context += \" \"\n", + "\n", + "# prompt = context + \"\\n\" + question\n", + "# indices_to_explain = [-2]\n", + "# target = None\n", + "\n", + "# print(prompt)\n", + "# print(answer)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Eliza's rate per hour for the first 40 hours she works each week is $10. Unrelated Sentence. She also receives an overtime pay of 1.2 times her regular hourly rate. Unrelated Sentence.\n", + "If Eliza worked for 45 hours this week, how much are her earnings for this week? Unrelated Sentence.\n", + "Eliza is entitled to 45 -40 = <<45-40=5>>5 hours overtime pay.\n", + "Her hourly rate for the overtime pay is $10 x 1.2 = $<<10*1.2=12>>12.\n", + "So, Eliza will receive $12 x 5 =$<<12*5=60>>60 for overtime pay.\n", + "Her regular weekly earning is $10 x 40 = $<<10*40=400>>400.\n", + "Thus, Eliza will receive a total of $400 + $60 = $<<400+60=460>>460 for this week's work.\n", + "#### 460\n", + "GT indices tensor([0, 2, 4])\n" + ] + } + ], + "source": [ + "# Math dataset\n", + "\n", + "# https://github.com/kojima-takeshi188/zero_shot_cot/blob/main/dataset/MultiArith/MultiArith.json\n", + "# https://github.com/kojima-takeshi188/zero_shot_cot/blob/main/dataset/grade-school-math/test.jsonl\n", + "\n", + "\n", + "with open('data/math_mine.json', 'r', encoding=\"utf-8\") as f:\n", + " data = json.load(f)\n", + "\n", + "index = 6\n", + "\n", + "dataset_item = data[index][\"question\"]\n", + "answer = data[index][\"answer\"]\n", + "target = None\n", + "\n", + "sentences = llm_attr_eval.create_sentences(dataset_item, tokenizer)\n", + "context_sentences = sentences[:-1]\n", + "question = sentences[-1][1:]\n", + "\n", + "context_sentences_w_dummy = llm_evaluator.add_dummy_facts_to_prompt(context_sentences)\n", + "question_sentences_w_dummy = llm_evaluator.add_dummy_facts_to_prompt([question])\n", + "prompt = \"\".join(context_sentences_w_dummy) + \"\\n\" + \"\".join(question_sentences_w_dummy)\n", + "attr_mask = torch.zeros((1, len(context_sentences_w_dummy) + len(question_sentences_w_dummy)))\n", + "attr_mask[:, ::2] = 1\n", + "attr_mask_indices = torch.where(attr_mask[0] == 1)[0]\n", + "indices_to_explain = [-2]\n", + "\n", + "print(prompt)\n", + "print(answer)\n", + "print(\"GT indices\", attr_mask_indices)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# # # Facts dataset \n", + "\n", + "# # # # dataset = load_dataset(\"fever/feverous\")[\"validation\"]\n", + "\n", + "# with open(\"data/10000_facts_9_choose_3.json\", \"r\") as f:\n", + "# data = json.load(f)\n", + "\n", + "# index = 5\n", + "# prompt = data[index][\"prompt\"]\n", + "# target = data[index][\"target\"]\n", + "\n", + "# generation_indices = data[index][\"generation_indices\"]\n", + "# attr_mask_indices = data[index][\"attr_mask_indices\"]\n", + "# indices_to_explain = data[index][\"indices_to_explain\"]\n", + "\n", + "# print(prompt)\n", + "# print(target)\n", + "# print(generation_indices)\n", + "# print(attr_mask_indices)\n", + "# print(indices_to_explain)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# DO NOT UNCOMMENT THIS BLOCK UNLESS YOU WANT TO REMAKE THE FACTS DATA\n", + "# # # # dataset = load_dataset(\"fever/feverous\")[\"validation\"]\n", + "\n", + "# # # # # making a Facts datset # DO NOT UNCOMMENT THIS BLOCK UNLESS YOU WANT TO REMAKE THE DATA\n", + "# # # # total = 500\n", + "# # # # N = len(dataset)\n", + "# # # # M = 5\n", + "# # # # K = 3\n", + "# # # # L = 2\n", + "\n", + "# # # # json_obj_array = []\n", + "# # # # entries_gathered= 0\n", + "# # # # with tqdm(total=total) as pbar:\n", + "# # # # while entries_gathered != total:\n", + " \n", + "# # # # # Random N indices for facts selection\n", + "# # # # fact_indices = random.sample(range(N), M)\n", + "# # # # facts = []\n", + "# # # # for idx in fact_indices:\n", + "# # # # fact = dataset[idx][\"claim\"]\n", + "# # # # if fact[-1] != \".\":\n", + "# # # # fact = fact + \".\"\n", + "# # # # facts.append(fact)\n", + "\n", + "# # # # if len(llm_attr_eval.create_sentences(\" \".join(facts), tokenizer)) != M:\n", + "# # # # continue\n", + "\n", + "# # # # generation_indices = torch.sort(torch.randperm(M)[:K])[0]\n", + "# # # # indices_to_explain = torch.sort(torch.randperm(K)[:L])[0]\n", + "# # # # explained_idx_locations = generation_indices[indices_to_explain]\n", + "# # # # prompt = \" \".join(facts) + \"\\nList \" + str(K) + \" of these facts.\"\n", + "# # # # target = \" \".join([facts[idx] for idx in generation_indices])\n", + "\n", + "# # # # json_obj_array.append({\"prompt\": prompt, \n", + "# # # # \"target\": target, \n", + "# # # # \"generation_indices\" : generation_indices.tolist(), \n", + "# # # # \"indices_to_explain\" : indices_to_explain.tolist(),\n", + "# # # # \"attr_mask_indices\" : explained_idx_locations.tolist()})\n", + "\n", + "# # # # entries_gathered += 1\n", + "# # # # pbar.update(1)\n", + "\n", + "# # # # with open('data/' + str(total) + '_facts_' + str(M) + '_choose_' + str (K) + '.json', 'w', encoding='utf-8') as f:\n", + "# # # # json.dump(json_obj_array, f, ensure_ascii=False, indent=4)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "<|begin_of_text|><|start_header_id|>system<|end_header_id|>\n", + "\n", + "Cutting Knowledge Date: December 2023\n", + "Today Date: 24 Sep 2025\n", + "\n", + "<|eot_id|><|start_header_id|>user<|end_header_id|>\n", + "\n", + "Context: Eliza's rate per hour for the first 40 hours she works each week is $10. Unrelated Sentence. She also receives an overtime pay of 1.2 times her regular hourly rate. Unrelated Sentence.\n", + "If Eliza worked for 45 hours this week, how much are her earnings for this week? Unrelated Sentence.\n", + "\n", + "\n", + "Query:<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n", + "\n", + "To find Eliza's earnings for the week, we need to calculate her regular earnings for the first 40 hours and her overtime earnings.\n", + "\n", + "Regular earnings for the first 40 hours:\n", + "40 hours * $10/hour = $400\n", + "\n", + "Overtime earnings:\n", + "45 hours - 40 hours = 5 hours\n", + "Overtime rate: 1.2 times regular rate = 1.2 * $10/hour = $12/hour\n", + "5 hours * $12/hour = $60\n", + "\n", + "Total earnings for the week:\n", + "Regular earnings + Overtime earnings = $400 + $60 = $460\n", + "\n", + "Therefore, Eliza's earnings for this week are $460.<|eot_id|>\n" + ] + } + ], + "source": [ + "new_generations = 512\n", + "\n", + "gen = model_forward(prompt, model, tokenizer, new_generations, print_response=True)\n", + "\n", + "total_gen_len = len(tokenizer(gen, add_special_tokens=False).input_ids)\n", + "batch_size = int(math.floor(mem_limit / total_gen_len))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# plt.rcParams['font.size'] = 10\n", + "\n", + "# IG attribution\n", + "# llm_attributor = llm_attr.LLMGradientAttribtion(model, tokenizer)\n", + "\n", + "# attr = llm_attributor.calculate_IG_per_generation(prompt, 20, baseline = tokenizer.eos_token_id, batch_size = 1, target = target)\n", + "\n", + "# attrs = attr.get_all_sentence_attrs(indices_to_explain)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "plt.rcParams['font.size'] = 10\n", + "\n", + "llm_attributor = llm_attr.LLMPerturbationAttribution(model, tokenizer)\n", + "\n", + "# perturbation attribution\n", + "attr = llm_attributor.calculate_feature_ablation_sentences(prompt, baseline = tokenizer.eos_token_id, target = target)\n", + "\n", + "# CLP attribution\n", + "# attr = llm_attributor.calculate_feature_ablation_sentences(prompt, baseline = tokenizer.eos_token_id, measure=\"KL\", target = target)\n", + "\n", + "# ReAGent attribution\n", + "# attr = llm_attributor.calculate_feature_ablation_sentences_mlm(prompt, target = target)\n", + "\n", + "attrs = attr.get_all_sentence_attrs(indices_to_explain)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAH2IAAAU3CAYAAACY0IDgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAC4jAAAuIwF4pT92AAEAAElEQVR4nOzdeZiWdb348c8szMIMDMyIILGmguCuo5JLLmm5pJ2Dnk5p5fJLIculMpfq5HIqOx5zyaOZ2rG0TEu01DK3I+pR0UBQ2RVEUFSWAWZj9vn94RWnx2eAWXnuYV6v6+KP+/M89/f+wAxc88/DO6u1tbU1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIkO9MLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHyUEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA4QuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4gixAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkjxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkjhA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkDhC7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDiCLEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiSPEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACSOEDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQOELsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQOIIsQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJI8QOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJI4QOwAAAAAAAAAAAAAAAAAA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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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mJqaQiaTKZTXqFEDampqBfb/epwAoKGhgadPn77VOImIiKjiMHFFREREHxxbW1s0bdoUnp6e+Omnn/DFF1/g4MGD+O233wD8fwIkIyOjwLa3b9+GiooKDAwMALx8/M3GxgZRUVGIjIxE06ZNUa1aNbRr1w4ZGRk4ffo0/vjjjxI9Jrhx40YAwPLly2FgYCD9fPnllwrr39TriaCi5ObmFkgQZWZmAvj/86SpqQkABSZMf9PElpGREf755x+FiekBICsrC7m5uTA2Nn6j9omIiOj9x8QVERERffCWLFkCAwMDzJ49G3K5HA0aNEDNmjWxfft2haTJ48ePERoaKr1pMJ+XlxeOHj2qMOeSjY0NateujdmzZ+PFixfFJq7u3buH3bt3o1WrVjh27FiBn4EDByI+Ph4XL14E8HIkEQClo4nKe5TRtm3bFJa3b98OANIbAE1MTKCpqYnk5GSFer///rvS2ADlcb+uXbt2ePToEfbs2aNQvnnzZmk9ERERfdw4OTsRERF98AwMDDBjxgxMnToV27dvl95cN3DgQHTt2hWjRo3C8+fP8f333+P+/fv47rvvFLZv164d1qxZgzt37iAwMFChPCgoCAYGBnBxcSkyhm3btuHZs2fw8/OTEkKvMjIywrZt27Bx40asWLECjRs3BgCsXLkSQ4YMgbq6Oho0aABdXV00btwYO3fuREhICKytraGpqSnVL60qVapg2bJlePToEZo1a4bY2FgsWLAAnTp1kubskslkGDRoEH755RfUrVsXDg4OOHPmjJTgelVRcb9u8ODB+PHHHzFkyBDcuHEDjRs3xsmTJ7Fw4UJ07ty5RKPYiIiI6MPGEVdERET0URg/fjxq166NefPmIS8vDwMGDMCePXtw9+5d9O3bF59//jn09PRw7NixApOst23bFioqKtDW1oarq6tUnp9Y8fT0VJjkXZmNGzeiRo0a6N69u9L1jRs3RosWLbB161bk5OTAw8MDM2bMwL59+9C6dWs0a9YMCQkJAIC5c+fC3d0dI0aMwCeffIJu3bqV+byoq6sjPDwckZGR8PHxwapVqzBixIgCbyVctmyZlPDz8fFBXFwcwsPDC7RXVNyv09TUlEabff/99+jUqROCg4MxefJkhIWFlfmYiIiI6MMhE69PKkBERERERERERFQJcMQVERERERERERFVSkxcERERERERERFRpcTEFRERERERERERVUpMXBERERERERERUaXExBUREREREREREVVKTFwREREREREREVGlpFbRAVRGcrkct2/fhq6uLmQyWUWHQ0RERERERET0QRFC4OHDhzA3N4eKSuHjqpi4UuL27duwsLCo6DCIiIiIiIiIiD5oN2/eRK1atQpdz8SVErq6ugBenjw9Pb0KjoaIiIiIiIiI6MOSnZ0NCwsLKQdTGCaulMh/PFBPT4+JKyIiIiIiIiKit6S4KZo4OTsREREREREREVVKFZq4On78OLp16wZzc3PIZDLs2bOn2G1iYmLg4uICTU1NWFtb46effipQJzQ0FHZ2dtDQ0ICdnR127979FqInIiIiIiIiIqK3qUITV48fP4aDgwNWr15dovppaWno3Lkz2rRpg8TERHz99dfw8/NDaGioVCcuLg59+/aFr68vzp8/D19fX/Tp0wenT59+W4dBRERERERERERvgUwIISo6CODlM427d+9G9+7dC60zbdo07N27FykpKVLZ6NGjcf78ecTFxQEA+vbti+zsbBw4cECq07FjRxgYGGDHjh0liiU7Oxv6+vp48OAB57giIiIiIiIiIipnJc29vFdzXMXFxaFDhw4KZd7e3jh79ixevHhRZJ3Y2NhC233+/Dmys7MVfoiIiIiIiIiIqGK9V28VzMzMhImJiUKZiYkJcnNzcefOHZiZmRVaJzMzs9B2Fy1ahLlz576VmImIiIiI6O2zmr6/okOg98yN77pUdAhEVALv1YgroOBrEvOfdHy1XFmdol6vOGPGDDx48ED6uXnzZjlGTEREREREREREZfFejbgyNTUtMHIqKysLampqMDIyKrLO66OwXqWhoQENDY3yD5iIiIiIiIiIiMrsvRpx5erqisjISIWyw4cPo2nTplBXVy+yTsuWLd9ZnERERERERERE9OYqdMTVo0ePcO3aNWk5LS0NSUlJMDQ0RO3atTFjxgzcunULmzdvBvDyDYKrV6+Gv78/RowYgbi4OGzcuFHhbYETJkyAm5sbFi9eDB8fH/z++++IiorCyZMn3/nxERERERERERFR2VXoiKuzZ8/CyckJTk5OAAB/f384OTlh9uzZAICMjAykp6dL9evUqYOIiAhER0fD0dER8+fPx6pVq/DZZ59JdVq2bImdO3ciKCgITZo0QXBwMEJCQtC8efN3e3BERERERERERPRGZCJ/dnOSZGdnQ19fHw8ePICenl5Fh0NERERERMXgWwWptPhWQaKKVdLcy3s1xxUREREREREREX08mLgiIiIiIiIiIqJKiYkrIiIiIiIiIiKqlJi4IiIiIiIiIiKiSomJKyIiIiIiIiIiqpSYuCIiIiIiIiIiokqJiSsiIiIiIiIiIqqUmLgiIiIiIiIiIqJKiYkrIiIiIiIiIiKqlJi4IiIiIiIiIiKiSomJKyIiIiIiIiIiqpSYuCIiIiIiIiIiokqJiSsiIiIiIiIiIqqUmLgiIiIiIiIiIqJKiYkrIiIiIiIiIiKqlJi4IiIiIiIiIiKiSomJKyIiIiIiIiIiqpSYuCIiIiIiIiIiokqJiSsiIiIiIiIiIqqUmLgiIiIiIiIiIqJKiYkrIiIiIiIiIiKqlJi4IiIiIiIiIiKiSomJKyIiIiIiIiIiqpSYuCIiIiIiIiIiokqJiSsiIiIiIiIiIqqUmLgiIiIiIiIiIqJKiYkrIiIiIiIiIiKqlCo8cbVmzRrUqVMHmpqacHFxwYkTJwqtO3ToUMhksgI/jRo1kuoEBwcrrfPs2bN3cThERERERERERFROKjRxFRISgokTJ2LmzJlITExEmzZt0KlTJ6Snpyutv3LlSmRkZEg/N2/ehKGhIXr37q1QT09PT6FeRkYGNDU138UhERERERERERFROanQxNXy5csxfPhwfPHFF7C1tUVgYCAsLCywdu1apfX19fVhamoq/Zw9exb37t3D559/rlBPJpMp1DM1NX0Xh0NEREREREREROWowhJXOTk5SEhIQIcOHRTKO3TogNjY2BK1sXHjRnh5ecHS0lKh/NGjR7C0tEStWrXQtWtXJCYmFtnO8+fPkZ2drfBDREREREREREQVq8ISV3fu3EFeXh5MTEwUyk1MTJCZmVns9hkZGThw4AC++OILhfKGDRsiODgYe/fuxY4dO6CpqYlWrVrh6tWrhba1aNEi6OvrSz8WFhZlOygiIiIiIiIiIio3FT45u0wmU1gWQhQoUyY4OBjVqlVD9+7dFcpbtGiBQYMGwcHBAW3atMGuXbtgY2ODH374odC2ZsyYgQcPHkg/N2/eLNOxEBERERERERFR+VGrqB0bGxtDVVW1wOiqrKysAqOwXieEwC+//AJfX19UqVKlyLoqKipo1qxZkSOuNDQ0oKGhUfLgiYiIiIiIiIjorauwEVdVqlSBi4sLIiMjFcojIyPRsmXLIreNiYnBtWvXMHz48GL3I4RAUlISzMzM3iheIiIiIiIiIiJ6typsxBUA+Pv7w9fXF02bNoWrqyvWr1+P9PR0jB49GsDLR/hu3bqFzZs3K2y3ceNGNG/eHPb29gXanDt3Llq0aIH69esjOzsbq1atQlJSEn788cd3ckxERERERERERFQ+KjRx1bdvX9y9exfz5s1DRkYG7O3tERERIb0lMCMjA+np6QrbPHjwAKGhoVi5cqXSNu/fv4+RI0ciMzMT+vr6cHJywvHjx/HJJ5+89eMhIiIiIiIiIqLyIxNCiDdp4NmzZ9DU1CyveCqF7Oxs6Ovr48GDB9DT06vocIiIiIiIqBhW0/dXdAj0nrnxXZeKDoHoo1bS3EuZ5riSy+WYP38+atasCR0dHfz1118AgFmzZmHjxo1li5iIiIiIiIiIiOgVZUpcLViwAMHBwViyZInCW/0aN26Mn3/+udyCIyIiIiIiIiKij1eZElebN2/G+vXrMXDgQKiqqkrlTZo0wZ9//lluwRERERERERER0cerTImrW7duoV69egXK5XI5Xrx48cZBERERERERERERlSlx1ahRI5w4caJA+a+//gonJ6c3DoqIiIiIiIiIiEitLBvNmTMHvr6+uHXrFuRyOcLCwpCamorNmzcjPDy8vGMkIiIiIiIiIqKPUJlGXHXr1g0hISGIiIiATCbD7NmzkZKSgn379qF9+/blHSMREREREREREX2EyjTiCgC8vb3h7e1dnrEQERERERERERFJyjTiKj4+HqdPny5Qfvr0aZw9e/aNgyIiIiIiIiIiIipT4mrs2LG4efNmgfJbt25h7NixbxwUERERERERERFRmRJXly9fhrOzc4FyJycnXL58+Y2DIiIiIiIiIiIiKlPiSkNDA//880+B8oyMDKiplXnaLCIiIiIiIiIiIkmZElft27fHjBkz8ODBA6ns/v37+Prrr/lWQSIiIiIiIiIiKhdlGh61bNkyuLm5wdLSEk5OTgCApKQkmJiYYMuWLeUaIBERERERERERfZzKlLiqWbMmkpOTsW3bNpw/fx5aWlr4/PPP0b9/f6irq5d3jERERERERERE9BEq84RU2traGDlyZHnGQkREREREREREJClz4urKlSuIjo5GVlYW5HK5wrrZs2e/cWBERERERERERPRxK1PiasOGDfjyyy9hbGwMU1NTyGQyaZ1MJmPiioiIiIiIiIiI3liZElcLFizAt99+i2nTppV3PERERERERERERAAAlbJsdO/ePfTu3bu8YyEiIiIiIiIiIpKUKXHVu3dvHD58uLxjISIiIiIiIiIikpTpUcF69eph1qxZ+OOPP9C4cWOoq6srrPfz8yuX4IiIiIiIiIiI6OMlE0KI0m5Up06dwhuUyfDXX3+9UVAVLTs7G/r6+njw4AH09PQqOhwiIiIiIiqG1fT9FR0CvWdufNelokMg+qiVNPdSphFXaWlpZQ6MiIiIiIiIiIioJMo0x1W+nJwcpKamIjc3t7ziISIiIiIiIiIiAlDGxNWTJ08wfPhwVK1aFY0aNUJ6ejqAl3Nbfffdd+UaIBERERERERERfZzKlLiaMWMGzp8/j+joaGhqakrlXl5eCAkJKbfgiIiIiIiIiIjo41WmxNWePXuwevVqtG7dGjKZTCq3s7PD9evXS9XWmjVrUKdOHWhqasLFxQUnTpwotG50dDRkMlmBnz///FOhXmhoKOzs7KChoQE7Ozvs3r27dAdIREREREREREQVrkyJq3///Rc1atQoUP748WOFRFZxQkJCMHHiRMycOROJiYlo06YNOnXqJD16WJjU1FRkZGRIP/Xr15fWxcXFoW/fvvD19cX58+fh6+uLPn364PTp0yU/QCIiIiIiIiIiqnBlSlw1a9YM+/f//+tm85NVGzZsgKura4nbWb58OYYPH44vvvgCtra2CAwMhIWFBdauXVvkdjVq1ICpqan0o6qqKq0LDAxE+/btMWPGDDRs2BAzZsxAu3btEBgYWLqDJCIiIiIiIiKiCqVWlo0WLVqEjh074vLly8jNzcXKlStx6dIlxMXFISYmpkRt5OTkICEhAdOnT1co79ChA2JjY4vc1snJCc+ePYOdnR2++eYbeHp6Suvi4uIwadIkhfre3t5MXBERERERERERvWfKNOKqZcuWOHXqFJ48eYK6devi8OHDMDExQVxcHFxcXErUxp07d5CXlwcTExOFchMTE2RmZirdxszMDOvXr0doaCjCwsLQoEEDtGvXDsePH5fqZGZmlqpNAHj+/Dmys7MVfoiIiIiIiIiIqGKVacQVADRu3BibNm164wBenxNLCFHoPFkNGjRAgwYNpGVXV1fcvHkTS5cuhZubW5naBF6OIJs7d25ZwiciIiIiIiIiorekTImr4iZPr127drFtGBsbQ1VVtcBIqKysrAIjporSokULbN26VVo2NTUtdZszZsyAv7+/tJydnQ0LC4sSx0BEREREREREROWvTIkrKyurIkcw5eXlFdtGlSpV4OLigsjISPTo0UMqj4yMhI+PT4ljSUxMhJmZmbTs6uqKyMhIhXmuDh8+jJYtWxbahoaGBjQ0NEq8TyIiIiIiIiIievvKlLhKTExUWH7x4gUSExOxfPlyfPvttyVux9/fH76+vmjatClcXV2xfv16pKenY/To0QBejoS6desWNm/eDODlGwOtrKzQqFEj5OTkYOvWrQgNDUVoaKjU5oQJE+Dm5obFixfDx8cHv//+O6KionDy5MmyHCoREREREREREVWQMiWuHBwcCpQ1bdoU5ubm+P7779GzZ88StdO3b1/cvXsX8+bNQ0ZGBuzt7REREQFLS0sAQEZGhsJjiTk5OZg8eTJu3boFLS0tNGrUCPv370fnzp2lOi1btsTOnTvxzTffYNasWahbty5CQkLQvHnzshwqERERERERERFVEJkQQpRXY1evXoWjoyMeP35cXk1WiOzsbOjr6+PBgwfQ09Or6HCIiIiIiKgYVtP3V3QI9J658V2Xig6B6KNW0txLmUZcZWdnKywLIZCRkYGAgADUr1+/LE0SEREREREREREpKFPiqlq1agUmZxdCwMLCAjt37iyXwIiIiIiIiIiI6ONWpsTVsWPHFJZVVFRQvXp11KtXD2pqZWqSiIiIiIiIiIhIQZmyTO7u7uUdBxERERERERERkYISJ6727t1b4kY//fTTMgVDRERERERERESUr8SJq+7du5eonkwmQ15eXlnjISIiIiIiIiIiAlCKxJVcLn+bcRARERERERERESlQKWlFQ0ND3L17FwAwbNgwPHz48K0FRUREREREREREVOLEVU5ODh48eAAA2LRpE549e/bWgiIiIiIiIiIiIirxo4Kurq7o3r07XFxcIISAn58ftLS0lNb95Zdfyi1AIiIiIiIiIiL6OJU4cbV161asWLEC169fh0wmw4MHDzjqioiIiIiIiIiI3poSJ65MTEzw3XffAQDq1KmDLVu2wMjI6K0FRkREREREREREH7cSJ65elZaWVt5xEBERERERERERKShT4goAjhw5giNHjiArKwtyuVxhHee4IiIiIiIiIiKiN1WmxNXcuXMxb948NG3aFGZmZpDJZOUdFxERERERERERfeTKlLj66aefEBwcDF9f3/KOh4iIiIiIiIiICACgUpaNcnJy0LJly/KOhYiIiIiIiIiISFKmxNUXX3yB7du3l3csREREREREREREkjI9Kvjs2TOsX78eUVFRaNKkCdTV1RXWL1++vFyCIyIiIiIiIiKij1eZElfJyclwdHQEAFy8eLE84yEiIiIiIiIiIgJQxsTVsWPHyjsOIiIiIiIiIiIiBaVKXPXs2bPYOjKZDKGhoWUOiIiIiIiIiIiICChl4kpfX/9txUFERERERERERKSgVImroKCgtxUHERERERERERGRApWKDoCIiIiIiIiIiEgZJq6IiIiIiIiIiKhSYuKKiIiIiIiIiIgqJSauiIiIiIiIiIioUqrwxNWaNWtQp04daGpqwsXFBSdOnCi0blhYGNq3b4/q1atDT08Prq6uOHTokEKd4OBgyGSyAj/Pnj1724dCRERERERERETlqEITVyEhIZg4cSJmzpyJxMREtGnTBp06dUJ6errS+sePH0f79u0RERGBhIQEeHp6olu3bkhMTFSop6enh4yMDIUfTU3Nd3FIRERERERERERUTtQqcufLly/H8OHD8cUXXwAAAgMDcejQIaxduxaLFi0qUD8wMFBheeHChfj999+xb98+ODk5SeUymQympqZvNXYiIiIiIiIiInq7KmzEVU5ODhISEtChQweF8g4dOiA2NrZEbcjlcjx8+BCGhoYK5Y8ePYKlpSVq1aqFrl27FhiR9brnz58jOztb4YeIiIiIiIiIiCpWhSWu7ty5g7y8PJiYmCiUm5iYIDMzs0RtLFu2DI8fP0afPn2ksoYNGyI4OBh79+7Fjh07oKmpiVatWuHq1auFtrNo0SLo6+tLPxYWFmU7KCIiIiIiIiIiKjcVPjm7TCZTWBZCFChTZseOHQgICEBISAhq1Kghlbdo0QKDBg2Cg4MD2rRpg127dsHGxgY//PBDoW3NmDEDDx48kH5u3rxZ9gMiIiIiIiIiIqJyUWFzXBkbG0NVVbXA6KqsrKwCo7BeFxISguHDh+PXX3+Fl5dXkXVVVFTQrFmzIkdcaWhoQENDo+TBExERERERERHRW1dhI66qVKkCFxcXREZGKpRHRkaiZcuWhW63Y8cODB06FNu3b0eXLl2K3Y8QAklJSTAzM3vjmImIiIiIiIiI6N2p0LcK+vv7w9fXF02bNoWrqyvWr1+P9PR0jB49GsDLR/hu3bqFzZs3A3iZtBo8eDBWrlyJFi1aSKO1tLS0oK+vDwCYO3cuWrRogfr16yM7OxurVq1CUlISfvzxx4o5SCIiIiIiIiIiKpMKTVz17dsXd+/exbx585CRkQF7e3tERETA0tISAJCRkYH09HSp/rp165Cbm4uxY8di7NixUvmQIUMQHBwMALh//z5GjhyJzMxM6Ovrw8nJCcePH8cnn3zyTo+NiIiIiIiIiIjejEwIISo6iMomOzsb+vr6ePDgAfT09Co6HCIiIiIiKobV9P0VHQK9Z258V/zUM0T09pQ091LhbxUkIiIiIiIiIiJShokrIiIiIiIiIiKqlJi4IiIiIiIiIiKiSomJKyIiIiIiIiIiqpSYuCIiIiIiIiIiokqJiSsiIiIiIiIiIqqUmLgiIiIiIiIiIqJKiYkrIiIiIiIiIiKqlJi4IiIiIiIiIiKiSomJKyIiIiIiIiIiqpSYuCIiIiIiIiIiokqJiSsiIiIiIiIiIqqUmLgiIiIiIiIiIqJKiYkrIiIiIiIiIiKqlJi4IiIiIiIiIiKiSomJKyIiIiIiIiIiqpTUKjoAevuspu+v6BDoPXLjuy4VHQIRERERERERAI64IiIiIiIiIiKiSoqJKyIiIiIiIiIiqpSYuCIiIiIiIiIiokqJiSsiIiIiIiIiIqqUmLgiIiIiIiIiIqJKiYkrIiIiIiIiIiKqlJi4IiIiIiIiIiKiSomJKyIiIiIiIiIiqpTUKjoAIiKiD5HV9P0VHQK9R25816WiQyAiIiKqlDjiioiIiIiIiIiIKqUKT1ytWbMGderUgaamJlxcXHDixIki68fExMDFxQWampqwtrbGTz/9VKBOaGgo7OzsoKGhATs7O+zevftthU9ERERERERERG9JhSauQkJCMHHiRMycOROJiYlo06YNOnXqhPT0dKX109LS0LlzZ7Rp0waJiYn4+uuv4efnh9DQUKlOXFwc+vbtC19fX5w/fx6+vr7o06cPTp8+/a4Oi4iIiIiIiIiIyoFMCCEqaufNmzeHs7Mz1q5dK5XZ2tqie/fuWLRoUYH606ZNw969e5GSkiKVjR49GufPn0dcXBwAoG/fvsjOzsaBAwekOh07doSBgQF27NhRoriys7Ohr6+PBw8eQE9Pr6yHV2lwnhUqDc6zQlQ+2PdSabDvJXpz7HeptNj3ElWskuZeKmxy9pycHCQkJGD69OkK5R06dEBsbKzSbeLi4tChQweFMm9vb2zcuBEvXryAuro64uLiMGnSpAJ1AgMDC43l+fPneP78ubT84MEDAC9P4odA/vxJRYdA75EP5bonqmjse6k02PcSvTn2u1Ra7HuJKlb+v8HixlNVWOLqzp07yMvLg4mJiUK5iYkJMjMzlW6TmZmptH5ubi7u3LkDMzOzQusU1iYALFq0CHPnzi1QbmFhUdLDIfpg6AdWdARERB8f9r1ERO8e+16iyuHhw4fQ19cvdH2FJa7yyWQyhWUhRIGy4uq/Xl7aNmfMmAF/f39pWS6X47///oORkVGR29H7Kzs7GxYWFrh58+YH8TgofVx4/dL7itcuva947dL7jNcvva947X74hBB4+PAhzM3Ni6xXYYkrY2NjqKqqFhgJlZWVVWDEVD5TU1Ol9dXU1GBkZFRkncLaBAANDQ1oaGgolFWrVq2kh0LvMT09PXaC9N7i9UvvK1679L7itUvvM16/9L7itfthK2qkVb4Ke6tglSpV4OLigsjISIXyyMhItGzZUuk2rq6uBeofPnwYTZs2hbq6epF1CmuTiIiIiIiIiIgqpwp9VNDf3x++vr5o2rQpXF1dsX79eqSnp2P06NEAXj7Cd+vWLWzevBnAyzcIrl69Gv7+/hgxYgTi4uKwceNGhbcFTpgwAW5ubli8eDF8fHzw+++/IyoqCidPnqyQYyQiIiIiIiIiorKp0MRV3759cffuXcybNw8ZGRmwt7dHREQELC0tAQAZGRlIT0+X6tepUwcRERGYNGkSfvzxR5ibm2PVqlX47LPPpDotW7bEzp078c0332DWrFmoW7cuQkJC0Lx583d+fFR5aWhoYM6cOQUeESV6H/D6pfcVr116X/HapfcZr196X/HapXwyUdx7B4mIiIiIiIiIiCpAhc1xRUREREREREREVBQmroiIiIiIiIiIqFJi4oqIiIiIiIiIiColJq7orRk6dCi6d+8uLXt4eGDixIkVFg/RmwgODka1atUqbP9WVlYIDAyssP1T5fB6v/quVPT1/7Z8qMf1Iano3xH73g+fEAIjR46EoaEhZDIZkpKSytTOh3rf+zb+DZTk3Kxfvx4WFhZQUVHhv8EKwL6XKhsmrqhMoqOjIZPJlP5kZmYq3SYsLAzz588vtxg8PDwQHBxcbu2VxI0bN97opobKpqgPz2rVqr3z66Ck3uWH7uPHjzFt2jRYW1tDU1MT1atXh4eHB8LDw8t1PxWVOPlYrFu3Dg4ODtDW1ka1atXg5OSExYsXV3RYH6y+ffviypUrFR1GpcW+t3jse98/r5/LgwcPIjg4GOHh4dJbzl9XGe57PybZ2dkYN24cpk2bhlu3bmHkyJEVHdI7xb63eOx7Pz5qFR0Avd9SU1Ohp6enUFajRg2ldQ0NDd9FSGXy4sULqKurV3QYbywvLw8ymQwqKsxJl9SHcs5Gjx6NM2fOYPXq1bCzs8Pdu3cRGxuLu3fvVnRoVEIbN26Ev78/Vq1aBXd3dzx//hzJycm4fPlyRYf2zr2rPllLSwtaWlpvfT9UEPteqiyuX78OMzMztGzZsti6H8p9b0nk5OSgSpUqFbLv9PR0vHjxAl26dIGZmVmZ2/lQ7u/LE/teel+931csVbgaNWrA1NRU4aewjvDVYcGFfXM1dOhQAC9vInx8fGBiYgIdHR00a9YMUVFRRcYSEBCA2rVrQ0NDA+bm5vDz8yuyrqOjI3755RdYW1tDQ0MDQggcPHgQrVu3RrVq1WBkZISuXbvi+vXr0nZ16tQBADg5OUEmk8HDw0NaFxQUBFtbW2hqaqJhw4ZYs2ZNkfF6eHhg3LhxGDdunLS/b775BkIIqU5OTg6mTp2KmjVrQltbG82bN0d0dLS0Pv8bmfDwcNjZ2UFDQwN///13kfv9kOWPiAsLC4OnpyeqVq0KBwcHxMXFSXUKO2fFnevXFXeNenh44O+//8akSZOk6ztfbGws3NzcoKWlBQsLC/j5+eHx48fS+qysLHTr1g1aWlqoU6cOtm3bVuyx79u3D19//TU6d+4MKysruLi4YPz48RgyZIhUp6TX06FDh2BrawsdHR107NgRGRkZAF7+u9m0aRN+//136Zjyt7916xb69u0LAwMDGBkZwcfHBzdu3JDazv/GaunSpTAzM4ORkRHGjh2LFy9eSHWeP3+OqVOnwsLCAhoaGqhfvz42btworb98+TI6d+4MHR0dmJiYwNfXF3fu3Cn23Lwv9u3bhz59+mD48OGoV68eGjVqhP79+yv9xr6o81jaaxkAli9fjsaNG0NbWxsWFhYYM2YMHj16VGj98+fPw9PTE7q6utDT04OLiwvOnj0rrQ8NDUWjRo2goaEBKysrLFu2rMj9F9YnP3jwACNHjkSNGjWgp6eHtm3b4vz58wrb7t27F02bNoWmpiaMjY3Rs2fPEp+LV7/VTk1NhUwmw59//lng3FhZWUl9c3HX4W+//YbGjRtDS0sLRkZG8PLyUvj3/SFi38u+9301dOhQjB8/Hunp6ZDJZLCysiqyfmW5733w4AFUVVWRkJAA4OXjjoaGhmjWrJlUZ8eOHQpJnwsXLqBt27ZS3zRy5EiFfj7/Wlm0aBHMzc1hY2OjdN9BQUHQ19dHZGQkgOKvj8ePH2Pw4MHQ0dGBmZlZsZ8HwcHBaNy4MQDA2toaMplMuqbXrl2LunXrokqVKmjQoAG2bNmisK1MJsNPP/0EHx8faGtrY8GCBUXu633Hvpd978eEiSuqEC1btkRGRob0c/ToUWhqasLNzQ0A8OjRI3Tu3BlRUVFITEyEt7c3unXrhvT0dKXt/fbbb1ixYgXWrVuHq1evYs+ePdKHXmGuXbuGXbt2ITQ0VHr07/Hjx/D390d8fDyOHDkCFRUV9OjRA3K5HABw5swZAEBUVBQyMjIQFhYGANiwYQNmzpyJb7/9FikpKVi4cCFmzZqFTZs2FRnDpk2boKamhtOnT2PVqlVYsWIFfv75Z2n9559/jlOnTmHnzp1ITk5G79690bFjR1y9elWq8+TJEyxatAg///wzLl26VOg3fx+TmTNnYvLkyUhKSoKNjQ369++P3Nxcab2yc1aSc/2q4q7RsLAw1KpVC/PmzZOuc+DljaO3tzd69uyJ5ORkhISE4OTJkxg3bpzU9tChQ3Hjxg0cPXoUv/32G9asWYOsrKwij9nU1BQRERF4+PBhoXVKej0tXboUW7ZswfHjx5Geno7JkycDACZPnow+ffpIH+oZGRlo2bIlnjx5Ak9PT+jo6OD48eM4efKk9OGfk5MjtX3s2DFcv34dx44dw6ZNmxAcHKww3H3w4MHYuXMnVq1ahZSUFPz000/Q0dEBAGRkZMDd3R2Ojo44e/YsDh48iH/++Qd9+vQp8ry8T0xNTfHHH38Um3wu7jyW9loGABUVFaxatQoXL17Epk2bcPToUUydOrXQ+gMHDkStWrUQHx+PhIQETJ8+XfpWOyEhAX369EG/fv1w4cIFBAQEYNasWcU+2qCsT+7SpQsyMzMRERGBhIQEODs7o127dvjvv/8AAPv370fPnj3RpUsXJCYm4siRI2jatGmZzkWDBg3g4uJS4IZ5+/btGDBgAGQyWbHXYUZGBvr3749hw4YhJSUF0dHR6Nmzp8IXEh8y9r3Kse+tvFauXIl58+ahVq1ayMjIQHx8/FvZT3nf9+rr68PR0VH6Izo5OVn6b3Z2NoCXyTJ3d3cAL6+vjh07wsDAAPHx8fj1118RFRWlcP0DwJEjR5CSkoLIyEilj1wtXboUkydPxqFDh9C+ffsSXR9TpkzBsWPHsHv3bhw+fBjR0dFSwk2Zvn37SgmRM2fOICMjAxYWFti9ezcmTJiAr776ChcvXsSoUaPw+eef49ixYwrbz5kzBz4+Prhw4QKGDRtW6H4+JOx7lWPf+4ERRGVw7NgxAUBoa2sr/NjY2Eh1hgwZInx8fKRld3d3MWHChAJt3blzR9StW1eMGTOmyH3a2dmJH374Qem6ZcuWCRsbG5GTk1Oi+OfMmSPU1dVFVlZWkfWysrIEAHHhwgUhhBBpaWkCgEhMTFSoZ2FhIbZv365QNn/+fOHq6lpo2+7u7sLW1lbI5XKpbNq0acLW1lYIIcS1a9eETCYTt27dUtiuXbt2YsaMGUIIIYKCggQAkZSUVPQBv+eCgoKEvr6+0nX6+voiKChICPH/v5+ff/5ZWn/p0iUBQKSkpEhtvX7OSnquC4sh3+vXqKWlpVixYoVCHV9fXzFy5EiFshMnTggVFRXx9OlTkZqaKgCIP/74Q1qfkpIiABRo61UxMTGiVq1aQl1dXTRt2lRMnDhRnDx5stTHCEBcu3ZNWv/jjz8KExMTafn1f9dCCLFx40bRoEEDhWv5+fPnQktLSxw6dEjaztLSUuTm5kp1evfuLfr27SuEENJxR0ZGKj2+WbNmiQ4dOiiU3bx5UwAQqamphZ6X98nt27dFixYtBABhY2MjhgwZIkJCQkReXp5Up7jzWJLfc0ns2rVLGBkZScuvX/+6uroiODhY6bYDBgwQ7du3VyibMmWKsLOzK3R/yvrkI0eOCD09PfHs2TOFunXr1hXr1q0TQgjh6uoqBg4cqLTNsvy7Xr58ubC2tpaW86/LS5cuCSGKvw4TEhIEAHHjxo1Cj/V9wr6Xfe+H2Pe+fi5XrFghLC0ti9ymst33CiGEv7+/6Nq1qxBCiMDAQNGrVy/h7Ows9u/fL4QQwsbGRqxdu1YIIcT69euFgYGBePTokbT9/v37hYqKisjMzJTiNzExEc+fP1fYT/6/p+nTpwszMzORnJwsrSvu+nj48KGoUqWK2Llzp7T+7t27QktLS+m5yZeYmCgAiLS0NKmsZcuWYsSIEQr1evfuLTp37iwtAxATJ04stN33Bfte9r0fYt/7pjjHFb2REydOQFdXV1pWUyvdJfXixQt89tlnqF27NlauXCmVP378GHPnzkV4eDhu376N3NxcPH36tNBvnnr37o3AwEBYW1ujY8eO6Ny5M7p161ZkPJaWlqhevbpC2fXr1zFr1iz88ccfuHPnjjTSKj09XelknQDw77//4ubNmxg+fDhGjBghlefm5kJfX7/I42/RooXCUFpXV1csW7YMeXl5OHfuHIQQBYZqP3/+HEZGRtJylSpV0KRJkyL387F59XzkD5PPyspCw4YNARQ8ZyU9168q7TWaLyEhAdeuXVMY1SGEgFwuR1paGq5cuQI1NTWFUSMNGzYs9s0ubm5u+Ouvv/DHH3/g1KlTOHr0KFauXIm5c+di1qxZJT7GqlWrom7dutKymZlZsd965R/Tq30BADx79kzhUdtGjRpBVVVVoe0LFy4AAJKSkqCqqip9O6xsH8eOHZO+iXrV9evXC32k4X1iZmaGuLg4XLx4ETExMYiNjcWQIUPw888/4+DBg9LjKEWdx7Jcy8DLbwUXLlyIy5cvIzs7G7m5uXj27BkeP34MbW3tAvX9/f3xxRdfYMuWLfDy8kLv3r2l6yYlJQU+Pj4K9Vu1aoXAwEDk5eUpxP6q1/vkhIQEPHr0qEDcT58+la6rpKQkhX73VWU5F/369cOUKVPwxx9/oEWLFti2bRscHR1hZ2cnxVTUddihQwe0a9cOjRs3hre3Nzp06IBevXrBwMBA6f4+NOx72fd+6CrLfS/w8tGsjRs3Qi6XIyYmBu3atUPt2rURExMDZ2dnXLlyRfq9pqSkSC/+yNeqVSvI5XKkpqbCxMQEANC4cWOl81otW7YMjx8/xtmzZ2FtbS2VF3d9PH36FDk5OXB1dZXKDQ0N0aBBg1KcNUjH8Pok7a1atVI4jwAU/g1/LNj3su/9GDBxRW+kTp06b/Sq1C+//BLp6emIj49X+PCfMmUKDh06hKVLl6JevXrQ0tJCr169FIZfvsrCwgKpqamIjIxEVFQUxowZg++//x4xMTGFTsqo7I+xbt26wcLCAhs2bIC5uTnkcjns7e0L3S8AKbm1YcMGNG/eXGFdYX+glYRcLpfmL3i9nVc7MS0tLYXk14dIT08Pjx49KvBHb15eHh49elQgQfjq7zz/3OT/noCC56yk5/pVpb1GX93XqFGjlM7BVrt2baSmpirEXRrq6upo06YN2rRpg+nTp2PBggWYN28epk2bVuJjfP3fi0wmK/YxJ7lcrvQRKwAKiQhlbef/XoqbIFsul6Nbt25K37D3JhO3Vkb29vawt7fH2LFjcfLkSbRp0wYxMTHw9PQEUPR5LMu1/Pfff6Nz584YPXo05s+fD0NDQ5w8eRLDhw9XmIvhVQEBARgwYAD279+PAwcOYM6cOdi5cyd69OgBIUSB67e4awgo2CfL5XKYmZkpnXMj/3OnqOumLOfCzMwMnp6e2L59O1q0aIEdO3Zg1KhRCm0WdR2qqqoiMjISsbGxOHz4MH744QfMnDkTp0+fluZIfJ+w7y0Z9r0fj8py3wu8/MP94cOHOHfuHE6cOIH58+fDwsICCxcuhKOjI2rUqAFbW1sAUNov53u1XNm9MQC0adMG+/fvx65duzB9+nSpvLjro6hH1MtC2WfL62WFHcP7hH1vybDv/bgwcUUVZvny5QgJCUFcXFyB7P6JEycwdOhQ9OjRA8DL56pfnfBOGS0tLXz66af49NNPMXbsWDRs2BAXLlyAs7NzieK5e/cuUlJSsG7dOrRp0wYAcPLkSYU6+d9C5eXlSWUmJiaoWbMm/vrrLwwcOLBE+8r3xx9/FFiuX78+VFVV4eTkhLy8PGRlZUnxfKwaNmyIvLw8JCYmKnwjc+7cOeTl5ZXpm7tXleVcl+QarVKlisK1AgDOzs64dOkS6tWrp7RdW1tb5Obm4uzZs/jkk08AvJw0+v79+6U7KAB2dnbSyJnyup4KO6aQkBBpAu2yaNy4sfStsZeXV4H1zs7OCA0NhZWVVam/4X6f5Y/0Kenk3mX5PZ89exa5ublYtmyZNKpr165dxW5nY2MDGxsbTJo0Cf3790dQUBB69OgBOzu7An1nbGwsbGxsSpXMd3Z2RmZmJtTU1AqdMLlJkyY4cuQIPv/88wLrynrNDxw4ENOmTUP//v1x/fp19OvXTyGm4q5DmUyGVq1aoVWrVpg9ezYsLS2xe/du+Pv7lziGyoJ9L/vej7XvfRvK+743f56r1atXQyaTwc7ODubm5khMTER4eLjCSA47Ozts2rRJYRTtqVOnoKKiUqKRG5988gnGjx8Pb29vqKqqYsqUKQCKvz7q1asHdXV1/PHHH6hduzYA4N69ewqjwUrK1tYWJ0+exODBg6Wy2NhYKTn3IWHfy76XfW9BnJyd3khWVhYyMzMVfgr7hv5VUVFRmDp1KpYuXQpjY2Np2wcPHgB4+UEXFhaGpKQknD9/HgMGDFD45uB1wcHB2LhxIy5evIi//voLW7ZsgZaWFiwtLUt8LPlvhVi/fj2uXbuGo0ePFvhDo0aNGtDS0pImyMuPNyAgAIsWLcLKlStx5coVXLhwAUFBQVi+fHmR+7x58yb8/f2RmpqKHTt24IcffsCECRMAvPyjcODAgRg8eDDCwsKQlpaG+Ph4LF68GBERESU+rg+BnZ0dOnXqhGHDhiEqKgppaWmIiorC8OHD0alTJ+mP+7Iqy7kuyTVqZWWF48eP49atW9JbQKZNm4a4uDiMHTsWSUlJuHr1Kvbu3Yvx48cDeDlBdMeOHTFixAicPn0aCQkJ+OKLL4r9ZsbDwwPr1q1DQkICbty4gYiICHz99dfw9PSEnp5euV1PVlZWSE5ORmpqKu7cuYMXL15g4MCBMDY2ho+PD06cOIG0tDTExMRgwoQJ+N///lfidocMGYJhw4Zhz549SEtLQ3R0tJRAGTt2LP777z/0798fZ86cwV9//YXDhw9j2LBh0g3F6tWr0a5duxIfS2Xz5ZdfYv78+Th16hT+/vtv/PHHHxg8eDCqV6+u8JhFUcrye65bty5yc3Pxww8/SP3nTz/9VOg+nj59inHjxiE6Ohp///03Tp06hfj4eOmPh6+++gpHjhzB/PnzceXKFWzatAmrV6+WJjstKS8vL7i6uqJ79+44dOgQbty4gdjYWHzzzTfSGwznzJmDHTt2YM6cOUhJScGFCxewZMmSMp8LAOjZsyeys7Px5ZdfwtPTEzVr1pTWFXcdnj59GgsXLsTZs2eRnp6OsLAw/Pvvv+/tH1bse9n3fgx9b2lUlvvefB4eHti6dSvc3d0hk8lgYGAAOzs7hISEKLz5euDAgdDU1MSQIUNw8eJFHDt2DOPHj4evr6/0mGBxXF1dceDAAcybNw8rVqwAUPz1oaOjg+HDh2PKlCk4cuQILl68iKFDhxb6JsaiTJkyBcHBwfjpp59w9epVLF++HGFhYaX+bHkfsO9l38u+V4l3PKcWfSDyJ6lU9hMXFyeEKHqSyjlz5ijddsiQIUKIl5MNenp6Ci0tLWFhYSFWr15d6CSXQgixe/du0bx5c6Gnpye0tbVFixYtRFRUVKHxz5kzRzg4OBQoj4yMFLa2tkJDQ0M0adJEREdHCwBi9+7dUp0NGzYICwsLoaKiItzd3aXybdu2CUdHR1GlShVhYGAg3NzcRFhYWKExuLu7izFjxojRo0cLPT09YWBgIKZPn64w0V9OTo6YPXu2sLKyEurq6sLU1FT06NFDmhizJBMnfigePHggJk2aJOrVqyc0NTVFvXr1xMSJE8X9+/elOsomz793754AII4dOyaEKPyclfZcl+QajYuLE02aNBEaGhri1e72zJkzon379kJHR0doa2uLJk2aiG+//VZan5GRIbp06SI0NDRE7dq1xebNm5VOePmqhQsXCldXV2FoaCg0NTWFtbW18PPzE3fu3CnzMQrx8t/Wq7FnZWVJsb96XjMyMsTgwYOFsbGx0NDQENbW1mLEiBHiwYMHQgjlk1tOmDBB4d/Q06dPxaRJk4SZmZmoUqWKqFevnvjll1+k9VeuXBE9evQQ1apVE1paWqJhw4Zi4sSJ0r+ZOXPmFDvBbmX222+/ic6dO0vHb25uLj777DOFiXBLch6L+z0rs3z5cmFmZia0tLSEt7e32Lx5swAg7t27J4RQvDaeP38u+vXrJywsLKQ4x40bJ54+fapwLHZ2dkJdXV3Url1bfP/990Uee2F9cnZ2thg/frwwNzcX6urqwsLCQgwcOFCkp6dLdUJDQ6W+19jYWPTs2bPE56Kw/qB3794CgML1l6+o6/Dy5cvC29tbVK9eXWhoaAgbG5siJ1d+H7DvZd/7ofW9bzI5e2W57823b98+AUCsXr1aKpswYYIAIC5evKhQNzk5WXh6egpNTU1haGgoRowYIR4+fFjoecn3+r+BmJgYoa2tLVauXCmEKP76ePjwoRg0aJCoWrWqMDExEUuWLCn22JRNzi6EEGvWrBHW1tZCXV1d2NjYiM2bNyusf/2e/X3Gvpd974fW974pmRAfyTuaiSoZDw8PODo6IjAwsKJDISIiIiIiIqqU+KggERERERERERFVSkxcERERERERERFRpcRHBYmIiIiIiIiIqFLiiCsiIiIiIiIiIqqUmLiiQnl4eGDixIkVHYaCgIAAmJiYQCaTYc+ePe9kf46OjuXe7pMnT/DZZ59BT08PMpkM9+/fh5WVFSdqJ6IPwtvqO9937/ozjIjejqFDh6J79+4VHcYbKe6+88aNG5DJZEhKSnpnMb2J4OBgVKtWraLDIKK3hIkrem+kpKRg7ty5WLduHTIyMtCpU6dybf9d/iGxadMmnDhxArGxscjIyIC+vj7i4+MxcuTIMrf5vt1gENGHQVnfOXnyZBw5cqRiAqqk3vZnGBEVbdGiRZDJZAW+lB06dChkMpnCT4sWLSomyLegrAkdCwsLZGRkwN7evvyDIiIqJbWKDoDodTk5OahSpUqB8uvXrwMAfHx8IJPJytz+ixcvoK6uXubty8P169dha2urcDNQvXr1IrepDHETEeUrrK8GAB0dHejo6LzjiCq38voMI6LSi4+Px/r169GkSROl6zt27IigoCBpubC+raIV1e+WN1VVVZiamr6TfRERFYcjrqhIcrkcU6dOhaGhIUxNTREQEKCwPj09HT4+PtDR0YGenh769OmDf/75R1qvbCj1xIkT4eHhIS17eHhg3Lhx8Pf3h7GxMdq3b18gjoCAAHTr1g0AoKKiIt30y+VyzJs3D7Vq1YKGhgYcHR1x8OBBabv8UUi7du2Ch4cHNDU1sXXr1gLtW1lZAQB69OgBmUwmLefbsmULrKysoK+vj379+uHhw4fSOiEElixZAmtra2hpacHBwQG//fZboefUw8MDy5Ytw/HjxyGTyaRz8fqQbZlMhp9++gk+Pj7Q1tbGggULcO/ePQwcOBDVq1eHlpYW6tevL91o1alTBwDg5OSk0C4RVR4HDx5E69atUa1aNRgZGaFr165SQgP4/z4rLCwMnp6eqFq1KhwcHBAXF1dku0X1xampqZDJZPjzzz8Vtlm+fDmsrKyQ/46Wy5cvo3PnztDR0YGJiQl8fX1x584dqb6yvrqwvvP1RwXzPwsWLlwIExMTVKtWDXPnzkVubi6mTJkCQ0ND1KpVC7/88otCjLdu3ULfvn1hYGAAIyMj+Pj44MaNG4Weh+joaMhkMuzfvx8ODg7Q1NRE8+bNceHCBanO3bt30b9/f9SqVQtVq1ZF48aNsWPHDmn95s2bYWRkhOfPnyu0/dlnn2Hw4MGF7vvChQto27YttLS0YGRkhJEjR+LRo0fS+VD2GUZEb9+jR48wcOBAbNiwAQYGBkrraGhowNTUVPoxNDQsUdtLly6FmZkZjIyMMHbsWLx48UJad+/ePQwePBgGBgaoWrUqOnXqhKtXr0rrlT1SHRgYqHAPmt93Llq0CObm5rCxsQEArFmzBvXr14empiZMTEzQq1cvpfFFR0fj888/x4MHD6TRZK/eyz958gTDhg2Drq4uateujfXr10vrXh/JX9Q96Ov27duHatWqQS6XAwCSkpIgk8kwZcoUqc6oUaPQv39/aTk2NhZubm7Q0tKChYUF/Pz88PjxY2l9Tk4Opk6dipo1a0JbWxvNmzdHdHS00v0DL/v6Tz75BJ9++imePXtWaD0iej8wcUVF2rRpE7S1tXH69GksWbIE8+bNQ2RkJICXCZvu3bvjv//+Q0xMDCIjI3H9+nX07du3TPtRU1PDqVOnsG7dugLrJ0+eLH04ZmRkICMjAwCwcuVKLFu2DEuXLkVycjK8vb3x6aefKtwYAMC0adPg5+eHlJQUeHt7F2g/Pj4eABAUFISMjAxpGXj5LfmePXsQHh6O8PBwxMTE4LvvvpPWf/PNNwgKCsLatWtx6dIlTJo0CYMGDUJMTIzSYw0LC8OIESPg6uqKjIwMhIWFFXpe5syZAx8fH1y4cAHDhg3DrFmzcPnyZRw4cAApKSlYu3YtjI2NAQBnzpwBAERFRRXbLhFVjMePH8Pf3x/x8fE4cuQIVFRU0KNHD+nmPt/MmTMxefJkJCUlwcbGBv3790dubq7SNovrixs0aAAXFxds27ZNYbvt27djwIABkMlkyMjIgLu7OxwdHXH27FkcPHgQ//zzD/r06aOwzet9dVF95+uOHj2K27dv4/jx41i+fDkCAgLQtWtXGBgY4PTp0xg9ejRGjx6NmzdvAnj5B5Wnpyd0dHRw/PhxnDx5Ejo6OujYsSNycnKKPM9TpkzB0qVLER8fjxo1auDTTz+V/qB89uwZXFxcEB4ejosXL2LkyJHw9fXF6dOnAQC9e/dGXl4e9u7dK7V3584dhIeH4/PPP1e6vydPnqBjx44wMDBAfHw8fv31V0RFRWHcuHEACv8MI6K3b+zYsejSpQu8vLwKrRMdHY0aNWrAxsYGI0aMQFZWVrHtHjt2DNevX8exY8ewadMmBAcHIzg4WFo/dOhQnD17Fnv37kVcXByEEOjcubNCcqskjhw5gpSUFERGRiI8PBxnz56Fn58f5s2bh9TUVBw8eBBubm5Kt23ZsiUCAwOhp6cn9T2TJ0+W1i9btgxNmzZFYmIixowZgy+//LLAlxz5iroHfZ2bmxsePnyIxMREAEBMTAyMjY0V7o2jo6Ph7u4O4GXi39vbGz179kRycjJCQkJw8uRJqQ8FgM8//xynTp3Czp07kZycjN69e6Njx44F7vkB4H//+x/atGmDhg0bIiwsDJqamsWcZSKq9ARRIdzd3UXr1q0Vypo1ayamTZsmhBDi8OHDQlVVVaSnp0vrL126JACIM2fOCCGEGDJkiPDx8VFoY8KECcLd3V1hP46OjsXGs3v3bvH6JWtubi6+/fbbAjGOGTNGCCFEWlqaACACAwOLbR+A2L17t0LZnDlzRNWqVUV2drZUNmXKFNG8eXMhhBCPHj0SmpqaIjY2VmG74cOHi/79+xe6r9fPgRBCWFpaihUrVijEM3HiRIU63bp1E59//rnSNvOPNTExsdD9ElHlkpWVJQCICxcuCCH+/9/xzz//LNXJ71dTUlKUtlGSvnj58uXC2tpaWp+amioAiEuXLgkhhJg1a5bo0KGDQrs3b94UAERqaqoQovC+urC+08HBQVoeMmSIsLS0FHl5eVJZgwYNRJs2baTl3Nxcoa2tLXbs2CGEEGLjxo2iQYMGQi6XS3WeP38utLS0xKFDh5Sei2PHjgkAYufOnVLZ3bt3hZaWlggJCVG6jRBCdO7cWXz11VfS8pdffik6deokLQcGBgpra2uFWF61fv16YWBgIB49eiSV7d+/X6ioqIjMzEwhhPLPMCJ6u3bs2CHs7e3F06dPhRAv+7EJEyYo1Nm5c6cIDw8XFy5cEHv37hUODg6iUaNG4tmzZ4W2m9+n5ebmSmW9e/cWffv2FUIIceXKFQFAnDp1Slp/584doaWlJXbt2iWEKNhPCiHEihUrhKWlpcJ+TExMxPPnz6Wy0NBQoaenp3BvWpSgoCChr69foNzS0lIMGjRIWpbL5aJGjRpi7dq1QoiC95VF3YMq4+zsLJYuXSqEEKJ79+7i22+/FVWqVBHZ2dkiIyND4XPN19dXjBw5UmH7EydOCBUVFfH06VNx7do1IZPJxK1btxTqtGvXTsyYMUPhOFNTU0Xt2rXF+PHjC+2ziej9wxFXVKTX5wIwMzOTvoVKSUmBhYUFLCwspPV2dnaoVq0aUlJSSrWfpk2bljq27Oxs3L59G61atVIob9WqVYH9l6X9fFZWVtDV1ZWWXz0Hly9fxrNnz9C+fXtpThcdHR1s3rxZ4fGfsno97i+//BI7d+6Eo6Mjpk6ditjY2DfeBxG9O9evX8eAAQNgbW0NPT096RHf9PR0hXqv9r1mZmYAUOgIgJL0xf369cPff/+NP/74AwCwbds2ODo6ws7ODgCQkJCAY8eOKfRjDRs2lGLO9yZ9aaNGjaCi8v+3HSYmJmjcuLG0rKqqCiMjI+k4ExIScO3aNejq6koxGRoa4tmzZ8X2r66urtL/GxoaokGDBtK5yMvLw7fffosmTZrAyMgIOjo6OHz4sMLvYMSIETh8+DBu3boF4OWIsvwJnJVJSUmBg4MDtLW1pbJWrVpBLpcjNTW1pKeIiMrRzZs3MWHCBGzdurXIETd9+/ZFly5dYG9vj27duuHAgQO4cuUK9u/fX2T7jRo1gqqqqrT8+j2ympoamjdvLq03MjJS6ItKqnHjxgrzWrVv3x6WlpawtraGr68vtm3bhidPnpSqzXyvftbIZDKYmpoW+llT2ntQDw8PREdHQwiBEydOwMfHB/b29jh58iSOHTsGExMT6XMmISEBwcHBCp9B3t7ekMvlSEtLw7lz5yCEgI2NjUKdmJgYhc+Dp0+fonXr1ujevTtWrVrFx7KJPiCcnJ2K9Ppk4DKZTHqkRQih9APh1XIVFRVp/pR8yoZIv3qzX1qvx6Asrjdpv6hzkP/f/fv3o2bNmgr1NDQ0yrzPfK/H3alTJ/z999/Yv38/oqKi0K5dO4wdOxZLly59430R0dvXrVs3WFhYYMOGDTA3N4dcLoe9vX2BR99e7XdendNPmZL0xWZmZvD09MT27dvRokUL7NixA6NGjZLqyuVydOvWDYsXLy7QTn7iDCj/vrS4/lXZI45A8S+zUCb/XCxbtgwrVqxAYGAgGjduDG1tbUycOFHhd+Dk5AQHBwds3rwZ3t7euHDhAvbt21do24X9Dl7dLxG9WwkJCcjKyoKLi4tUlpeXh+PHj2P16tV4/vy5QuIpn5mZGSwtLZU+gvaq4u6RlSmPe2RdXV2cO3cO0dHROHz4MGbPno2AgADEx8eX+u2BRR3D60p7D+rh4YGNGzfi/PnzUFFRgZ2dHdzd3RETE4N79+5JjwkCL/v7UaNGwc/Pr0A7tWvXRnJyMlRVVZGQkFDgd/bqi0A0NDTg5eWF/fv3Y8qUKahVq1aJzwURVW4ccUVlZmdnh/T0dGk+EuDlCKQHDx7A1tYWwMs/Ll6fyyN/ksc3paenB3Nzc5w8eVKhPDY2Vtp/aairqyMvL69U29jZ2UFDQwPp6emoV6+ews+rox/KU/Xq1TF06FBs3boVgYGB0kSa+d/GlfYYiOjduHv3LlJSUvDNN9+gXbt2sLW1xb1799643ZL0xQAwcOBAhISEIC4uDtevX0e/fv2kdc7Ozrh06RKsrKwK9GXFJavK0neWhLOzM65evYoaNWoUiElfX7/IbfNHlgEvJxS+cuWK9M1+/jf/gwYNgoODA6ytrZX+gfrFF18gKCgIv/zyC7y8vIrs0+3s7JCUlKQwkfCpU6egoqIiTaZMRO9Wu3btcOHCBSQlJUk/TZs2xcCBA5GUlKQ0aQW87Ktv3rypkLQvLTs7O+Tm5kpz5+W3e+XKFYV75MzMTIXkVUnvkdXU1ODl5YUlS5YgOTkZN27cwNGjR5XWrVKlSrn10YXdgyqTP89VYGAg3N3dIZPJ4O7ujujoaIX5rYD//wx6va+vV68eqlSpAicnJ+Tl5SErK6vA+lfffKiiooItW7bAxcUFbdu2xe3bt8vluImo4jFxRWXm5eWFJk2aYODAgTh37hzOnDmDwYMHw93dXXqcpG3btjh79iw2b96Mq1evYs6cObh48WK5xTBlyhQsXrwYISEhSE1NxfTp05GUlIQJEyaUui0rKyscOXIEmZmZJf5jUldXF5MnT8akSZOwadMmXL9+HYmJifjxxx+xadOmUsdQnNmzZ+P333/HtWvXcOnSJYSHh0s3QDVq1ICWlpY0qfKDBw/Kff9EVHb5b8Zbv349rl27hqNHj8Lf3/+N2y1JXwwAPXv2RHZ2Nr788kt4enoqjBIdO3Ys/vvvP/Tv3x9nzpzBX3/9hcOHD2PYsGHF/sFTlr6zJAYOHAhjY2P4+PjgxIkTSEtLQ0xMDCZMmID//e9/RW47b948HDlyBBcvXsTQoUNhbGwsveG2Xr16iIyMRGxsLFJSUjBq1ChkZmYq3f+tW7ewYcMGDBs2rNhYNTU1MWTIEFy8eBHHjh3D+PHj4evrCxMTkzKfAyIqO11dXdjb2yv8aGtrw8jICPb29gBevnFw8uTJiIuLw40bNxAdHY1u3brB2NgYPXr0KPO+69evDx8fH4wYMQInT57E+fPnMWjQINSsWRM+Pj4AXo5I+vfff7FkyRJcv34dP/74Iw4cOFBs2+Hh4Vi1ahWSkpLw999/Y/PmzZDL5WjQoIHS+lZWVnj06BGOHDmCO3fulPmxwqLuQZXR19eHo6Mjtm7dKr3p2s3NDefOncOVK1cU3n49bdo0xMXFYezYsUhKSsLVq1exd+9ejB8/HgBgY2ODgQMHYvDgwQgLC0NaWhri4+OxePFiREREKOxXVVUV27Ztg4ODA9q2bau0fyei9w8TV1RmMpkMe/bsgYGBAdzc3ODl5QVra2uEhIRIdby9vTFr1ixMnToVzZo1w8OHD4t8nXhp+fn54auvvsJXX32Fxo0b4+DBg9i7dy/q169f6raWLVuGyMhIWFhYwMnJqcTbzZ8/H7Nnz8aiRYtga2sLb29v7Nu3T5q7pjxVqVIFM2bMQJMmTeDm5gZVVVXs3LkTwMtv31atWoV169bB3NxcujEiospBRUUFO3fuREJCAuzt7TFp0iR8//33b9xuSfpi4OUo1W7duuH8+fMYOHCgwjpzc3OcOnUKeXl58Pb2hr29PSZMmAB9fX2FeamUKWvfWZyqVavi+PHjqF27Nnr27AlbW1sMGzYMT58+hZ6eXpHbfvfdd5gwYQJcXFyQkZGBvXv3SqNSZ82aBWdnZ3h7e8PDwwOmpqZSUutVenp6+Oyzz6Cjo6N0/euxHjp0CP/99x+aNWuGXr16oV27dli9enVZD5+I3gFVVVVcuHABPj4+sLGxwZAhQ2BjY4O4uDiF+U3LIigoCC4uLujatStcXV0hhEBERIT0eJ6trS3WrFmDH3/8EQ4ODjhz5ozCG/8KU61aNYSFhaFt27awtbXFTz/9hB07dqBRo0ZK67ds2RKjR49G3759Ub16dSxZsqRMx1PUPWhhPD09kZeXJyWpDAwMYGdnh+rVqyskvZo0aYKYmBhcvXoVbdq0gZOTE2bNmqUw6i0oKAiDBw/GV199hQYNGuDTTz/F6dOnlY6GVVNTk85J27ZtpXm7rKysEBAQUKbjJ6KKJROFPYRNRERE9B6Jjo6Gp6cn7t27V+q5XpRp3749bG1tsWrVqjcPjoiIKszTp09haGiIiIgIeHp6VnQ4RFRKnJydiIiI6BX//fcfDh8+jKNHj3LUFBHRByAmJgZt27Zl0oroPcXEFREREdErnJ2dce/ePSxevLjQeWOIiOj90bFjR3Ts2LGiwyCiMuKjgkREREREREREVClxcnYiIiIiIiIiIqqUmLgiIiIiIiIiIqJKiYkrKjdDhw4t9pXh74Po6GjIZDLcv3+/okMpE5lMhj179lR0GET0EfDw8MDEiRMrOgwFwcHB5fJGQSL6MFXGfutdsbKyQmBgYEWHUaiP+XdDREVj4uojt2jRIshksgIfEkIIBAQEwNzcHFpaWvDw8MClS5cqJkgiIlLq+PHj6NatG8zNzUuctA4LC0P79u1RvXp16OnpwdXVFYcOHSpym8IS+mFhYZg/f/4bHAERERERUdGYuPqIxcfHY/369WjSpEmBdUuWLMHy5cuxevVqxMfHw9TUFO3bt8fDhw8rINKi5eTkVHQIlQLPA9HH5/Hjx3BwcMDq1atLvM3x48fRvn17REREICEhAZ6enujWrRsSExNLvX9DQ0Po6uqWerv30YsXLyo6BCKi90Jl6i8rUyxEVHZMXH2kHj16hIEDB2LDhg0wMDBQWCeEQGBgIGbOnImePXvC3t4emzZtwpMnT7B9+/Zi2166dCnMzMxgZGSEsWPHKnxg3Lt3D4MHD4aBgQGqVq2KTp064erVq9L6gIAAODo6KrQXGBgIKysraTn/kcRFixbB3NwcNjY2AIA1a9agfv360NTUhImJCXr16lVojH///Te6desGAwMDaGtro1GjRoiIiFCok5CQgKZNm6Jq1apo2bIlUlNTFdbv27cPLi4u0NTUhLW1NebOnYvc3Fyl+7tw4QJUVFRw584d6TyoqKigd+/eUp1FixbB1dVVWo6JicEnn3wCDQ0NmJmZYfr06Qrte3h4YNy4cfD394exsTHat2+vdN/z5s2DiYkJkpKSSn2eiKhy69SpExYsWICePXuWeJvAwEBMnToVzZo1Q/369bFw4ULUr18f+/btU1r/xo0b8PT0BAAYGBhAJpNh6NChAAo+1mFlZYUFCxZg8ODB0NHRgaWlJX7//Xf8+++/8PHxgY6ODho3boyzZ88q7CM2NhZubm7Q0tKChYUF/Pz88PjxY2l9WfqtQ4cOwdbWFjo6OujYsSMyMjIU1gcFBcHW1haamppo2LAh1qxZo3DMMpkMu3btgoeHBzQ1NbF169Zi90lE7we5XI6pU6fC0NAQpqamCAgIUFifnp4u9Vl6enro06cP/vnnHwDAgwcPoKqqioSEBAAv75sNDQ3RrFkzafsdO3bAzMys0P17eHhg/PjxmDhxIgwMDGBiYoL169fj8ePH+Pzzz6Grq4u6deviwIED0jbKHoPes2cPZDKZQtnevXvRtGlTaGpqwtjYuMDnw5MnTzBs2DDo6uqidu3aWL9+fZHn6uDBg2jdujWqVasGIyMjdO3aFdevX5fWF9VfFtXPFqa4382DBw8wcuRI1KhRA3p6emjbti3Onz8vrc//W+KXX36BtbU1NDQ0IIQodr9EVLkxcfWRGjt2LLp06QIvL68C69LS0pCZmYkOHTpIZRoaGnB3d0dsbGyR7R47dgzXr1/HsWPHsGnTJgQHByM4OFhaP3ToUJw9exZ79+5FXFwchBDo3Llzqb8NOXLkCFJSUhAZGYnw8HCcPXsWfn5+mDdvHlJTU3Hw4EG4ubkVefzPnz/H8ePHceHCBSxevBg6OjoKdWbOnIlly5bh7NmzUFNTw7Bhw6R1hw4dwqBBg+Dn54fLly9j3bp1CA4Oxrfffqt0f/b29jAyMkJMTAyAlyMejIyMcPz4calOdHQ03N3dAQC3bt1C586d0axZM5w/fx5r167Fxo0bsWDBAoV2N23aBDU1NZw6dQrr1q1TWCeEwIQJE7Bx40acPHkSjo6OpT5PRPThk8vlePjwIQwNDZWut7CwQGhoKAAgNTUVGRkZWLlyZaHtrVixAq1atUJiYiK6dOkCX19fDB48GIMGDcK5c+dQr149DB48WPpD4sKFC/D29kbPnj2RnJyMkJAQnDx5EuPGjQOAMvVbT548wdKlS7FlyxYcP34c6enpmDx5srR+w4YNmDlzJr799lukpKRg4cKFmDVrFjZt2qTQzrRp0+Dn54eUlBR4e3sXfzKJ6L2wadMmaGtr4/Tp01iyZAnmzZuHyMhIAC/vn7p3747//vsPMTExiIyMxPXr19G3b18AgL6+PhwdHREdHQ0ASE5Olv6bnZ0NQPGerqgYjI2NcebMGYwfPx5ffvklevfujZYtW+LcuXPw9vaGr68vnjx5UuLj2r9/P3r27IkuXbogMTERR44cQdOmTRXqLFu2DE2bNkViYiLGjBmDL7/8En/++WehbT5+/Bj+/v6Ij4/HkSNHoKKigh49ekAulyvUe72/LGk/q+y8FPW76dKlCzIzM6VRw87OzmjXrh3+++8/qY1r165h165dCA0Nlb64JaL3nKCPzo4dO4S9vb14+vSpEEIId3d3MWHCBGn9qVOnBABx69Ythe1GjBghOnToUGi7Q4YMEZaWliI3N1cq6927t+jbt68QQogrV64IAOLUqVPS+jt37ggtLS2xa9cuIYQQc+bMEQ4ODgrtrlixQlhaWirsx8TERDx//lwqCw0NFXp6eiI7O7tE56Bx48YiICBA6bpjx44JACIqKkoq279/vwAgnbM2bdqIhQsXKmy3ZcsWYWZmVug+e/bsKcaNGyeEEGLixIniq6++EsbGxuLSpUvixYsXQkdHRxw4cEAIIcTXX38tGjRoIORyubT9jz/+KHR0dEReXp4Q4uXvzdHRscB+AIhff/1VDBo0SDRs2FDcvHlTWlfa80RE7w8AYvfu3aXebsmSJcLQ0FD8888/hdbJ7xfv3bunUP7654elpaUYNGiQtJyRkSEAiFmzZkllcXFxAoDIyMgQQgjh6+srRo4cqdDuiRMnhIqKinj69Gmp+62goCABQFy7dk0q+/HHH4WJiYm0bGFhIbZv366w3fz584Wrq6sQQoi0tDQBQAQGBpZon0T0/nB3dxetW7dWKGvWrJmYNm2aEEKIw4cPC1VVVZGeni6tv3TpkgAgzpw5I4QQwt/fX3Tt2lUIIURgYKDo1auXcHZ2Fvv37xdCCGFjYyPWrl1b4hhyc3OFtra28PX1lcry+8+4uDghxMu+TV9fX6Gd3bt3i1f/nHN1dRUDBw4sdL+v99FyuVzUqFGjyFhfl5WVJQCICxcuCCEK7y+L62eVKe53c+TIEaGnpyeePXumUKdu3bpi3bp1QoiXf0uoq6uLrKysEh8TEVV+HHH1kbl58yYmTJiArVu3QlNTs8i6rw89FkIUKHtdo0aNoKqqKi2bmZkhKysLAJCSkgI1NTU0b95cWm9kZIQGDRogJSWlVMfRuHFjVKlSRVpu3749LC0tYW1tDV9fX2zbtq3Ib6j8/PywYMECtGrVCnPmzJG+LXvVq3N/5Q/3zj+WhIQEzJs3Dzo6OtLPiBEjkJGRUeh+PTw8pG/nYmJi4OnpCTc3N8TExCA+Ph5Pnz5Fq1atALw8V66urgrnu1WrVnj06BH+97//SWWvf4uWb9KkSYiLi8OJEydQq1atMp8nIvqw7dixAwEBAQgJCUGNGjXKpc1X+04TExMAL/vs18te7U+Dg4MV+lNvb2/I5XKkpaWVqd+qWrUq6tatKy2/+ln077//4ubNmxg+fLjCPhcsWKDw+AtQeB9LRO+31+d3ff1+1cLCAhYWFtJ6Ozs7VKtWTbpf9fDwwIkTJyCXyxETEwMPDw94eHggJiYGmZmZuHLlSrEjrl6NQVVVFUZGRkX2lSWRlJSEdu3alXi/MpkMpqamRe7j+vXrGDBgAKytraGnp4c6deoAePk45ate7S9L088WFR+g+LtJSEjAo0ePYGRkpNBuWlqaQruWlpaoXr16kfshoveLWkUHQO9WQkICsrKy4OLiIpXl5eXh+PHjWL16NZ4/fw5TU1MAQGZmpsLz+VlZWdKHaGHU1dUVlmUymTSUWBTyfPmrCTEVFZUC9ZQ9Rqitra2wrKuri3PnziE6OhqHDx/G7NmzERAQgPj4eKWvRf/iiy/g7e2N/fv34/Dhw1i0aBGWLVuG8ePHKz2W/Pjyj0Uul2Pu3LlK55UpLCHo4eGBCRMm4Nq1a7h48SLatGmD69evIyYmBvfv34eLi4s0ybGyJGH+eXm1/PXzkK99+/bYsWMHDh06hIEDB5b5PBHRhyskJATDhw/Hr7/+qvSx8bJS1ncW15+OGjUKfn5+BdqqXbs2qlSpUup+S9lnUX4fmr/fDRs2KHyRAkDhixeg8D6WiN5vxd2vKvui9tVyNzc3PHz4EOfOncOJEycwf/58WFhYYOHChXB0dESNGjVga2tb6hiK6itLco+spaVV5D4L2+/rj/29qlu3brCwsMCGDRtgbm4OuVwOe3v7Ai8FerW/LE0/W5r45HI5zMzMpC+CX/Xq5wH7bqIPD0dcfWTatWuHCxcuICkpSfpp2rQpBg4ciKSkJKiqqqJOnTowNTWVnicHXr6xLiYmBi1btizzvu3s7JCbm4vTp09LZXfv3sWVK1ekD/fq1asjMzNT4YO5pM+mq6mpwcvLC0uWLEFycjJu3LiBo0ePFlrfwsICo0ePRlhYGL766its2LChxMfi7OyM1NRU1KtXr8CPioryf1b581wtWLAADg4O0NPTg7u7O2JiYgrMhWBnZ4fY2FiF8xAbGwtdXV3UrFmz2Pg+/fRTbN++HV988QV27typsK6054mIPjw7duzA0KFDsX37dnTp0qXY+vkjXPPy8so9FmdnZ1y6dElpf5q/3/Lst0xMTFCzZk389ddfBfaXP5KAiD5ednZ2SE9Px82bN6Wyy5cv48GDB9L9av48V6tXr4ZMJoOdnR3atGmDxMREhIeHFzvaqiyqV6+Ohw8fKry44vV75CZNmuDIkSPlts+7d+8iJSUF33zzDdq1awdbW1vcu3ev2O3eVj/r7OyMzMxMqKmpFWjX2Ni4zO0SUeXHEVcfGV1dXdjb2yuUaWtrw8jISCqXyWSYOHGi9Kap/LdOVa1aFQMGDCjzvuvXrw8fHx+MGDEC69atg66uLqZPn46aNWvCx8cHwMtRSf/++y+WLFmCXr164eDBgzhw4AD09PSKbDs8PBx//fUX3NzcYGBggIiICMjlcjRo0EBp/YkTJ6JTp06wsbHBvXv3cPTo0WK/GXvV7Nmz0bVrV1hYWKB3795QUVFBcnIyLly4UGAC9XwymQxubm7YunUrJk2aBODlDUZOTg6OHDmCCRMmSHXHjBmDwMBAjB8/HuPGjUNqairmzJkDf3//QhNjr+vRowe2bNkCX19fqKmpoVevXqU+T0RUuT169AjXrl2TltPS0pCUlARDQ0PUrl0bADBjxgzcunULmzdvBvAyaTV48GCsXLkSLVq0QGZmJoCX39Tr6+sr3Y+lpSVkMhnCw8PRuXNnaGlpFXihRVlNmzYNLVq0wNixYzFixAhoa2tLL9/44Ycf3kq/FRAQAD8/P+jp6aFTp054/vw5zp49i3v37sHf379cjouI3k9eXl5o0qQJBg4ciMDAQOTm5mLMmDFwd3dXeBzOw8MDK1euRI8ePSCTyWBgYAA7OzuEhIRg1apV5R5X8+bNUbVqVXz99dcYP348zpw5o/ACJACYM2cO2rVrh7p166Jfv37Izc3FgQMHMHXq1DLt08DAAEZGRli/fj3MzMyQnp6O6dOnl2jbt9HPenl5wdXVFd27d8fixYvRoEED3L59GxEREejevTsf7yb6gHHEFSk1depUTJw4EWPGjEHTpk1x69YtHD58WHqUrayCgoLg4uKCrl27wtXVFUIIRERESMOCbW1tsWbNGvz4449wcHDAmTNnFN4EVZhq1aohLCwMbdu2ha2tLX766Sfs2LEDjRo1Ulo/Ly8PY8eOha2tLTp27IgGDRqU6BW9+by9vREeHo7IyEg0a9YMLVq0wPLly2FpaVnkdp6ensjLy4OHhweAl8msNm3aAABat24t1atZsyYiIiJw5swZODg4YPTo0Rg+fDi++eabEscIAL169cKmTZvg6+uLsLCwUp8nIqrczp49CycnJzg5OQEA/P394eTkhNmzZ0t1MjIyFOYiWbduHXJzczF27FiYmZlJP68mz19Xs2ZNzJ07F9OnT4eJiYn0xr/y0KRJE8TExODq1ato06YNnJycMGvWLOlR9bfRb33xxRf4+eefERwcjMaNG8Pd3R3BwcEccUVEkMlk2LNnDwwMDODm5gYvLy9YW1sjJCREod7r93QA4O7ujry8vLcy4srQ0BBbt25FREQEGjduLM1R+CoPDw/8+uuv2Lt3LxwdHdG2bVuFJx1KS0VFBTt37kRCQgLs7e0xadIkfP/99yXa9m30szKZDBEREXBzc8OwYcNgY2ODfv364caNG8VOZ0JE7zeZKGziISIiIiIiIiIiogrEEVdERERERERERFQpMXFFRERERERERESVEhNXRERERERERERUKTFxRURERERERERElRITV/TO5L+lpTILCAiAo6NjqbYpr+MaOnToG7dBRPS6GzduQCaTISkpqdzbLkufWZ48PDwwceLECts/EVF5CA4ORrVq1So6DOzZswf16tWDqqrqO+lbo6OjIZPJcP/+/ULrVPTnDBFVDkxcEb2hjIwMdOrU6a21f/z4cXTr1g3m5uaFJsmEEAgICIC5uTm0tLTg4eGBS5cuvbWYiIg+dlZWVggMDKzoMIjoA9C3b19cuXKlosPAqFGj0KtXL9y8eRPz588v17bL+kXD5MmTceTIkXKNhYjeP0xcEb0hU1NTaGholGnbp0+fws/PD9bW1ti+fTusrKzw6aefIjMzU6rz+PFjODg4YPXq1YW2s2TJEixfvhyrV69GfHw8TE1N0b59ezx8+LBMcRHR25WTk1PRIZRKZYv3xYsXb6VdIQRyc3PfSttE9PEpad+ppaWFGjVqvOVoivbo0SNkZWXB29sb5ubm0NXVLVM75f15oaOjAyMjo3Jtk4jeP0xcEYCXN+tLliyBtbU1tLS04ODggN9++01an5eXh+HDh6NOnTrQ0tJCgwYNsHLlygLt/PLLL2jUqBE0NDRgZmaGcePGKay/c+cOevTogapVq6J+/frYu3dvoTH98MMPaNy4sbS8Z88eyGQy/Pjjj1KZt7c3ZsyYIS3v27cPLi4u0NTUhLW1NebOnavwR8iDBw8wcuRI1KhRA3p6emjbti3Onz9faAxpaWmoV68evvzyS8jlcqV1Xh0FlZOTg3HjxsHMzAyampqwsrLCokWLCm1/4cKF2LVrF3744Qd07doVW7duRbNmzRQ+9Dt16oQFCxagZ8+eStsQQiAwMBAzZ85Ez549YW9vj02bNuHJkyfYvn17ofsmonfHw8MD48aNg7+/P4yNjdG+fXsAwOXLl9G5c2fo6OjAxMQEvr6+uHPnjrTdw4cPMXDgQGhra8PMzAwrVqwo8K21spGY1apVQ3BwsNJYStKfDx06FN27d8eiRYtgbm4OGxubIo9vy5YtsLKygr6+Pvr166eQNH/+/Dn8/PxQo0YNaGpqonXr1oiPj5fWK3tEJr+/z5f/qMgvv/wCa2traGhoQAihsM28efMUPjPyubi4YPbs2Urjzn9M5dChQ2jatCk0NDRw4sQJXL9+HT4+PjAxMYGOjg6aNWuGqKgoaTsPDw/8/fffmDRpEmQymUKssbGxcHNzg5aWFiwsLODn54fHjx8Xef6IqOKVx72wsr4z/3HtsLAweHp6omrVqnBwcEBcXJy03ev9YH6fV1TfWpLPhzVr1qB+/frQ1NSEiYkJevXqpfTYo6OjpURV27ZtIZPJEB0dDQAIDQ2V7u2trKywbNkyhW2trKywYMECDB06FPr6+hgxYkSB9ocOHYqYmBisXLlS6jNv3LghrU9ISEDTpk1RtWpVtGzZEqmpqQXOxauxfvLJJ9DW1ka1atXQqlUr/P3330qPi4g+HExcEQDgm2++QVBQENauXYtLly5h0qRJGDRoEGJiYgAAcrkctWrVwq5du3D58mXMnj0bX3/9NXbt2iW1sXbtWowdOxYjR47EhQsXsHfvXtSrV09hP3PnzkWfPn2QnJyMzp07Y+DAgfjvv/+UxpT/uFv+H3ExMTEwNjaWYsrNzUVsbCzc3d0BAIcOHcKgQYPg5+eHy5cvY926dQgODsa3334L4OUNSZcuXZCZmYmIiAgkJCTA2dkZ7dq1UxrDxYsX0apVK/Tu3Rtr166Fikrx/1xWrVqFvXv3YteuXUhNTcXWrVthZWVVaP3ExER069YNXbp0gZ6eHlq3bo1Zs2ahdu3axe4rX1paGjIzM9GhQwepTENDA+7u7oiNjS1xO0T0dm3atAlqamo4deoU1q1bh4yMDLi7u8PR0RFnz57FwYMH8c8//6BPnz7SNv7+/jh16hT27t2LyMhInDhxAufOnXujOErSnwPAkSNHkJKSgsjISISHhxfa3vXr17Fnzx6Eh4cjPDwcMTEx+O6776T1U6dORWhoKDZt2oRz586hXr168Pb2LrTvL8y1a9ewa9cuhIaGKp2va9iwYbh8+bJCUiw5ORmJiYnFziE4depULFq0CCkpKWjSpAkePXqEzp07IyoqComJifD29ka3bt2Qnp4OAAgLC0OtWrUwb948ZGRkICMjAwBw4cIFeHt7o2fPnkhOTkZISAhOnjxZ4EscIqp8yuNeGCi875w5cyYmT56MpKQk2NjYoH///kWO8Cyuby3u8+Hs2bPw8/PDvHnzkJqaioMHD8LNzU3pvl5NFoWGhiIjIwMtW7ZEQkIC+vTpg379+uHChQsICAjArFmzCnwx8v3338Pe3h4JCQmYNWtWgfZXrlwJV1dXjBgxQuozLSwsFM7NsmXLcPbsWaipqWHYsGFK48zNzUX37t3h7u6O5ORkxMXFYeTIkQpfHhDRB0rQR+/Ro0dCU1NTxMbGKpQPHz5c9O/fv9DtxowZIz777DNp2dzcXMycObPQ+gDEN998o7BfmUwmDhw4oLS+XC4XxsbG4rfffhNCCOHo6CgWLVokatSoIYQQIjY2VqipqYmHDx8KIYRo06aNWLhwoUIbW7ZsEWZmZkIIIY4cOSL09PTEs2fPFOrUrVtXrFu3TgghxJw5c4SDg4OIjY0VhoaG4vvvvy/0eF49rt27dwshhBg/frxo27atkMvlxW4nhBALFy4UxsbGYseOHUWea2X7ynfq1CkBQNy6dUuhfMSIEaJDhw4lioOI3i53d3fh6OioUDZr1qwC/0Zv3rwpAIjU1FSRnZ0t1NXVxa+//iqtv3//vqhataqYMGGCVKasX9DX1xdBQUFCCCHS0tIEAJGYmFhofK/350OGDBEmJibi+fPnRR7XnDlzRNWqVUV2drZUNmXKFNG8eXMhxMt+Xl1dXWzbtk1an5OTI8zNzcWSJUuEEEIEBQUJfX19hXZ3794tXr1FmTNnjlBXVxdZWVkK9dzd3RXORadOncSXX34pLU+cOFF4eHgUGv+xY8cEALFnz54ij1MIIezs7MQPP/wgLVtaWooVK1Yo1PH19RUjR45UKDtx4oRQUVERT58+LXYfRFQxyuteWFnfmd8H//zzz1LZpUuXBACRkpIihCjYDxbXt5bk8yE0NFTo6ekptFGUe/fuCQDi2LFjUtmAAQNE+/btFepNmTJF2NnZScuWlpaie/fuxbb/en8txP/3wVFRUVLZ/v37BQCpz8y/NxdCiLt37woAIjo6ukTHREQfDrUKyJVRJXP58mU8e/ZMenQlX05ODpycnKTln376CT///DP+/vtvPH36FDk5OdLQ3aysLNy+fRvt2rUrcl9NmjSR/l9bWxu6urrIyspSWlcmk8HNzQ3R0dFo164dLl26hNGjR2Pp0qVISUlBdHQ0nJ2doaOjA+DlMOP4+HhphBXwclj3s2fP8OTJEyQkJODRo0cFnpN/+vQprl+/Li2np6fDy8sLCxYswKRJk4o8ntcNHToU7du3R4MGDdCxY0d07dpVYSTU66ZMmQI1NTV8++23uHTpEs6dO4fBgwdjypQpUFdXL9W+X/+2SQjBb6CIKpGmTZsqLCckJODYsWNSH/aq69ev4+nTp3jx4gU++eQTqVxfXx8NGjR441iK6s/zNW7cGFWqVCm2LSsrK4W5UMzMzKR+/fr163jx4gVatWolrVdXV8cnn3yClJSUUsVsaWmJ6tWrF1lnxIgRGDZsGJYvXw5VVVVs27atwGMtyrz+u3n8+DHmzp2L8PBw3L59G7m5uXj69Kk04qowCQkJuHbtGrZt2yaVCSEgl8uRlpYGW1vbYmMhonevPO6F8xXWd756D2xmZgbg5f1zw4YNlcZUVN/6119/Ffv50L59e1haWsLa2hodO3ZEx44dpek6SiolJQU+Pj4KZa1atUJgYCDy8vKgqqoKoGAfWlqFnZvXn0AwNDTE0KFD4e3tjfbt28PLywt9+vSRtiGiDxcTVyTN3bR//37UrFlTYV3+pOO7du3CpEmTsGzZMri6ukJXVxfff/89Tp8+DeDlpJIl8XoyRiaTFTp3FPDyccH169fjxIkTcHBwQLVq1eDm5oaYmBhER0fDw8ND4Tjmzp2rdC4oTU1NyOVymJmZSc/sv+rVeQWqV68Oc3Nz7Ny5E8OHD4eenl6Jjg0AnJ2dkZaWhgMHDiAqKgp9+vSBl5eXwhwJr1JTU8OUKVMwZcoU9OnTBz169MCECRPw6NEjLFy4sET7NDU1BQBkZmYqfHBnZWXBxMSkxLET0dulra2tsCyXy9GtWzcsXry4QF0zMzNcvXoVgPKk9KtkMlmBsqImLy+uPy8s3sIU1a/nx1VUYl1FRaVE8Zcknm7dukFDQwO7d++GhoYGnj9/js8++6zY7V5ve8qUKTh06BCWLl2KevXqQUtLC7169Sp20mG5XI5Ro0bBz8+vwLrSPAJORO9WedwL5yusr3q1r8zv/4q6By5r35pPV1cX586dQ3R0NA4fPozZs2cjICAA8fHxBeYVLIyyL0Ff76+Bkn9eFKY05yYoKAh+fn44ePAgQkJC8M033yAyMhItWrR4oxiIqHJj4opgZ2cHDQ0NpKenS/NFve7EiRNo2bIlxowZI5W9OkpJV1cXVlZWOHLkCDw9PcstNg8PD0yYMAG//fablKRyd3dHVFQUYmNjMWHCBKmus7MzUlNTC8yr9er6zMxMqKmpFTnvlJaWFsLDw9G5c2d4e3vj8OHDpXqzip6eHvr27Yu+ffuiV69e6NixI/777z8YGhoWuV3VqlXRv39/nD17FidOnCjx/urUqQNTU1NERkZK3wrm5OQgJiZG6R/ERFQ5ODs7IzQ0FFZWVlBTK/hxXLduXairq+PMmTPSXCDZ2dm4evWqQl9dvXp1aY4lALh69SqePHlS6H6L68/LU7169VClShWcPHkSAwYMAPAyKXX27FlpAuHq1avj4cOHePz4sfTHj7I5rEpCTU0NQ4YMQVBQEDQ0NNCvX79SjS7Id+LECQwdOhQ9evQA8PJtW69OJAwAVapUQV5enkKZs7MzLl26VOjnEBFVTuVxL/wulfTzQU1NDV5eXvDy8sKcOXNQrVo1HD16tNAX/rzOzs4OJ0+eVCiLjY2FjY2NNNqqpJT1mWXl5OQEJycnzJgxA66urti+fTsTV0QfOCauCLq6upg8eTImTZoEuVyO1q1bIzs7G7GxsdDR0cGQIUNQr149bN68GYcOHUKdOnWwZcsWxMfHo06dOlI7AQEBGD16NGrUqIFOnTrh4cOHOHXqFMaPH1/m2Ozt7WFkZIRt27bh999/B/AymfXVV18BAFq3bi3VnT17Nrp27QoLCwv07t0bKioqSE5OxoULF7BgwQJ4eXnB1dUV3bt3x+LFi9GgQQPcvn0bERER6N69u8IwZ21tbezfvx+dOnVCp06dcPDgQaWP87xuxYoVMDMzg6OjI1RUVPDrr7/C1NS00G+25syZg+bNm6N58+YQQuDs2bP4/fff0bVrV6nOo0ePcO3aNWk5LS0NSUlJMDQ0RO3atSGTyTBx4kQsXLgQ9evXR/369bFw4UJUrVpV+kMRAAYPHoyaNWsW+ZZDInp3xo4diw0bNqB///6YMmUKjI2Nce3aNezcuRMbNmyArq4uhgwZgilTpsDQ0BA1atTAnDlzoKKiovANeNu2bbF69Wq0aNECcrkc06ZNK/JR45L05+VFW1sbX375pXQMtWvXxpIlS/DkyRMMHz4cANC8eXNUrVoVX3/9NcaPH48zZ84U+kbEkvjiiy+kR/JOnTpVpjbq1auHsLAwdOvWDTKZDLNmzSrw7b+VlRWOHz+Ofv36QUNDA8bGxpg2bRpatGiBsWPHYsSIEdDW1pYmaf7hhx8AADNmzMCtW7ewefPmMh8jEZWv8roXfpfxFvf5EB4ejr/++gtubm4wMDBAREQE5HJ5qR43/+qrr9CsWTPMnz8fffv2RVxcHFavXo01a9aUOmYrKyucPn0aN27cgI6OTrFf6CqTlpaG9evX49NPP4W5uTlSU1Nx5coVDB48uNRtEdH7hW8VJADA/PnzMXv2bCxatAi2trbw9vbGvn37pA/j0aNHo2fPnujbty+aN2+Ou3fvKnzjBABDhgxBYGAg1qxZg0aNGqFr167Soy5lJZPJpG+O2rRpA+Dlc/D6+vpwcnJSeIzP29sb4eHhiIyMRLNmzdCiRQssX74clpaWUlsRERFwc3PDsGHDYGNjg379+uHGjRtKH6nT0dHBgQMHIIRA586dS/Q6cx0dHSxevBhNmzZFs2bNcOPGDURERBT6RsJ69erh22+/Rb169bBlyxZ07doVHh4eWLBggVTn7Nmz0jdLwMu3yDg5OSm83n3q1KmYOHEixowZg6ZNm+LWrVsFRoqlp6crjMogooplbm6OU6dOIS8vD97e3rC3t8eECROgr68v9RnLly+Hq6srunbtCi8vL7Rq1Qq2trbQ1NSU2lm2bBksLCzg5uaGAQMGYPLkyUWOMipJf16evvvuO3z22Wfw9fWFs7Mzrl27hkOHDsHAwADAyzlLtm7dioiICDRu3Bg7duxAQEBAmfdXv359tGzZEg0aNEDz5s3L1MaKFStgYGCAli1bolu3bvD29oazs7NCnXnz5uHGjRuoW7euNPdWkyZNEBMTg6tXr6JNmzZwcnLCrFmzFB7jzsjIKHauLCJ698rjXvhdKu7zoVq1aggLC0Pbtm1ha2uLn376CTt27ECjRo1KvA9nZ2fs2rULO3fuhL29PWbPno158+YV+6ZWZSZPngxVVVXY2dmhevXqZeoHq1atij///BOfffYZbGxsMHLkSIwbNw6jRo0qdVtE9H6RCWUPKhPROzd06NA3GmVARB++x48fo2bNmli2bJk0YokUCSHQsGFDjBo1Cv7+/hUdDhHRO8HPByL6kPFRQSIiokoqMTERf/75Jz755BM8ePAA8+bNA4ACb3mil7KysrBlyxbcunULn3/+eUWHQ0T01vDzgYg+JkxcEVUSHG1FRMosXboUqampqFKlClxcXHDixAkYGxtXdFiVkomJCYyNjbF+/XrpUUQiog8VPx+I6GPBRwWJiIiIiIiIiKhS4uTsRERERERERERUKTFxRURERERE9BEKDg5GtWrVKjoMIqIiMXFFREREREREBSQnJ6NHjx6oUaMG9PX10atXL9y5c6eiwyKijwwTV0RERERERFTAiRMn0KpVKxw7dgyHDx/GhQsXMGXKlIoOi4g+MkxcERERERERVQL79u1DtWrVIJfLAQBJSUmQyWQKyaJRo0ahf//+AIDY2Fi4ublBS0sLFhYW8PPzw+PHj6W6OTk5mDp1KmrWrAltbW00b94c0dHRhe7/7t27+OSTT/Dpp5/i2bNnGDt2LCZPnoxGjRqhefPm8Pb2xs2bN9/OwRMRFYKJKyIiIiIiokrAzc0NDx8+RGJiIgAgJiYGxsbGiImJkepER0fD3d0dFy5cgLe3N3r27Ink5GSEhITg5MmTGDdunFT3888/x6lTp7Bz504kJyejd+/e6NixI65evVpg3//73//Qpk0bNGzYEGFhYdDU1FRYf/78eWzevBnDhg17S0dPRKScTAghKjoIIiIiIiIiAlxcXDBgwAB89dVX6NGjB5o1a4a5c+fizp07ePz4MczMzJCSkoKFCxdCS0sL69atk7Y9efIk3N3d8fjxY9y6dQv169fH//73P5ibm0t1vLy88Mknn2DhwoUIDg7GxIkTcebMGbRv3x4+Pj5YuXIlZDKZQkzJycnw8PDA119/jcmTJ7+zc0FEBABqFR0AERERERERveTh4YHo6Gj4+/vjxIkTWLBgAUJDQ3Hy5Encv38fJiYmaNiwIRISEnDt2jVs27ZN2lYIAblcjrS0NFy8eBFCCNjY2Ci0//z5cxgZGUnLT58+RevWrdG/f3+sXLlSaUwBAQHw9vZm0oqIKgQTV0RERERERJWEh4cHNm7ciPPnz0NFRQV2dnZwd3dHTEwM7t27B3d3dwCAXC7HqFGj4OfnV6CN2rVrIzk5GaqqqkhISICqqqrCeh0dHen/NTQ04OXlhf3792PKlCmoVatWgfbS0tLg4+NTzkdKRFQyTFwRERERERFVEvnzXAUGBsLd3R0ymQzu7u5YtGgR7t27hwkTJgAAnJ2dcenSJdSrV09pO05OTsjLy0NWVhbatGlT6P5UVFSwZcsWDBgwAG3btkV0dLTCo4UAsG3bNlSrVq3cjpGIqDQ4OTsREREREVEloa+vD0dHR2zduhUeHh4AXiazzp07hytXrkhl06ZNQ1xcHMaOHYukpCRcvXoVe/fuxfjx4wEANjY2GDhwIAYPHoywsDCkpaUhPj4eixcvRkREhMI+VVVVsW3bNjg4OKBt27bIzMxUWD9+/HiEhYW99WMnIlKGiSsiIiIiIqJKxNPTE3l5eVKSysDAAHZ2dqhevTpsbW0BAE2aNEFMTAyuXr2KNm3awMnJCbNmzYKZmZnUTlBQEAYPHoyvvvoKDRo0wKefforTp0/DwsKiwD7V1NSwY8cONGrUCG3btkVWVpa07vr167hz587bPWgiokLwrYJERERERERERFQpccQVERERERERERFVSkxcERERERERERFRpcTEFRERERERERERVUpMXBERERERERERUaXExBUREREREREREVVKTFwREREREREREVGlxMQVERERERERERFVSkxcERERERERERFRpcTEFRERERERERERVUpMXBERERERERERUaXExBUREREREREREVVKTFwREREREREREVGl9H8dEsLzvhuDUwAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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xx8Kdd3d3QWAAl8vX75Uuu39+/cLACIwMLDA+I4ePSoAiBUrVkj73KpVK6GtrS0ACHd3d6luYGCgqFOnjlBVVRUARFBQkBRfo0aNlLbv7u6u0EZKSooAIJYuXSrmz58vatWqJdTV1YWjo6M4duxYvvXDwsKEg4OD0NLSEtbW1mLt2rVi7ty54s3LzILiPnXqlAAgTp06le/YNG/eXGhqagodHR3Rrl07ce7cOYU6edv5999/FcqDgoIEAJGSklLAUSUiIqLKQibEa2OwiYiIiIiIiIiIKgjOcUVERERERERERBUSE1dERERERERERFQhMXFFREREREREREQVEhNXRERERERERERUITFxRUREREREREREFRITV0REREREREREVCGplXcAFZFcLsc///wDPT09yGSy8g6HiIiIiIiIiOiDIoTAo0ePYG5uDhWVgsdVMXGlxD///AMLC4vyDoOIiIiIiIiI6IN2584d1KpVq8DlTFwpoaenB+DVwdPX1y/naIiIiIiIiIiIPixZWVmwsLCQcjAFYeJKibzbA/X19Zm4IiIiIiIiIiJ6R4qaoomTsxMRERERERERUYVUromr06dPw9vbG+bm5pDJZNi/f3+R60RGRsLZ2RmampqwtrbGDz/8kK/O3r17YWdnBw0NDdjZ2WHfvn3vIHoiIiIiIiIiInqXyjVx9eTJEzRt2hRr164tVv2UlBR07twZrVu3Rnx8PL744gv4+flh7969Up3o6Gj07dsXvr6+uHTpEnx9fdGnTx+cP3/+Xe0GERERERERERG9AzIhhCjvIIBX9zTu27cP3bt3L7DOjBkzcODAASQlJUllY8aMwaVLlxAdHQ0A6Nu3L7KysnDkyBGpTseOHWFoaIhdu3YVK5asrCwYGBggMzOTc1wREREREREREZWx4uZeKtUcV9HR0ejQoYNCmZeXF2JjY/Hy5ctC60RFRRXY7osXL5CVlaXwIiIiIiIiIiKi8lWpniqYnp4OU1NThTJTU1Pk5OTg3r17MDMzK7BOenp6ge0uWbIE8+fPfycxExERERHRu2c183B5h0CVzO1vupR3CERUDJVqxBWQ/zGJeXc6vl6urE5hj1ecNWsWMjMzpdedO3fKMGIiIiIiIiIiIiqNSjXiqkaNGvlGTmVkZEBNTQ3GxsaF1nlzFNbrNDQ0oKGhUfYBExERERERERFRqVWqEVeurq4IDw9XKDt+/DhcXFxQpUqVQuu0bNnyvcVJRERERERERERvr1xHXD1+/Bg3b96U3qekpCAhIQFGRkaoXbs2Zs2ahbt372Lr1q0AXj1BcO3atfD398fIkSMRHR2NzZs3KzwtcNKkSXBzc8PSpUvh4+ODX3/9FSdOnMDZs2ff+/4REREREREREVHpleuIq9jYWDg6OsLR0REA4O/vD0dHR8yZMwcAkJaWhtTUVKl+nTp1EBYWhoiICDg4OGDhwoVYs2YNPvvsM6lOy5YtsXv3bgQFBaFJkyYIDg5GSEgImjdv/n53joiIiIiIiIiI3opM5M1uTpKsrCwYGBggMzMT+vr65R0OEREREREVgU8VpJLiUwWJyldxcy+Vao4rIiIiIiIiIiL6eDBxRUREREREREREFRITV0REREREREREVCExcUVERERERERERBUSE1dERERERERERFQhMXFFREREREREREQVEhNXRERERERERERUITFxRUREREREREREFRITV0REREREREREVCExcUVERERERERERBUSE1dERERERERERFQhMXFFREREREREREQVEhNXRERERERERERUITFxRUREREREREREFRITV0REREREREREVCExcUVERERERERERBUSE1dERERERERERFQhMXFFREREREREREQVEhNXRERERERERERUITFxRUREREREREREFRITV0REREREREREVCExcUVERERERERERBUSE1dERERERERERFQhMXFFREREREREREQVEhNXRERERERERERUITFxRUREREREREREFRITV0REREREREREVCGVe+Jq3bp1qFOnDjQ1NeHs7IwzZ84UWHfo0KGQyWT5Xo0aNZLqBAcHK63z/Pnz97E7RERERERERERURso1cRUSEoLJkyfjyy+/RHx8PFq3bo1OnTohNTVVaf3Vq1cjLS1Net25cwdGRkbo3bu3Qj19fX2FemlpadDU1Hwfu0RERERERERERGWkXBNXK1euxIgRI/D555/D1tYWgYGBsLCwwPr165XWNzAwQI0aNaRXbGwsHjx4gGHDhinUk8lkCvVq1KjxPnaHiIiIiIiIiIjKULklrrKzsxEXF4cOHToolHfo0AFRUVHFamPz5s1o3749LC0tFcofP34MS0tL1KpVC127dkV8fHyh7bx48QJZWVkKLyIiIiIiIiIiKl/llri6d+8ecnNzYWpqqlBuamqK9PT0ItdPS0vDkSNH8PnnnyuUN2zYEMHBwThw4AB27doFTU1NtGrVCjdu3CiwrSVLlsDAwEB6WVhYlG6niIiIiIiIiIiozJT75OwymUzhvRAiX5kywcHBqFq1Krp3765Q3qJFCwwaNAhNmzZF69atsWfPHtjY2OC7774rsK1Zs2YhMzNTet25c6dU+0JERERERERERGVHrbw2bGJiAlVV1XyjqzIyMvKNwnqTEAI//fQTfH19oa6uXmhdFRUVNGvWrNARVxoaGtDQ0Ch+8ERERERERERE9M6V24grdXV1ODs7Izw8XKE8PDwcLVu2LHTdyMhI3Lx5EyNGjChyO0IIJCQkwMzM7K3iJSIiIiIiIiKi96vcRlwBgL+/P3x9feHi4gJXV1ds3LgRqampGDNmDIBXt/DdvXsXW7duVVhv8+bNaN68Oezt7fO1OX/+fLRo0QL169dHVlYW1qxZg4SEBHz//ffvZZ+IiIiIiIiIiKhslGviqm/fvrh//z4WLFiAtLQ02NvbIywsTHpKYFpaGlJTUxXWyczMxN69e7F69WqlbT58+BCjRo1Ceno6DAwM4OjoiNOnT+OTTz555/tDRERERERERERlRyaEEG/TwPPnz6GpqVlW8VQIWVlZMDAwQGZmJvT19cs7HCIiIiIiKoLVzMPlHQJVMre/6VLeIRB91IqbeynVHFdyuRwLFy5EzZo1oauriz///BMAMHv2bGzevLl0ERMREREREREREb2mVImrRYsWITg4GMuWLVN4ql/jxo3x448/lllwRERERERERET08SpV4mrr1q3YuHEjBg4cCFVVVam8SZMm+OOPP8osOCIiIiIiIiIi+niVKnF19+5d1KtXL1+5XC7Hy5cv3zooIiIiIiIiIiKiUiWuGjVqhDNnzuQr//nnn+Ho6PjWQREREREREREREamVZqW5c+fC19cXd+/ehVwuR2hoKJKTk7F161YcOnSorGMkIiIiIiIiIqKPUKlGXHl7eyMkJARhYWGQyWSYM2cOkpKScPDgQXh6epZ1jERERERERERE9BEq1YgrAPDy8oKXl1dZxkJERERERERERCQp1YirmJgYnD9/Pl/5+fPnERsb+9ZBERERERERERERlSpxNX78eNy5cydf+d27dzF+/Pi3DoqIiIiIiIiIiKhUtwpeu3YNTk5O+codHR1x7dq1tw6KypbVzMPlHQJVIre/6VLeIRAREREREREBKOWIKw0NDfzvf//LV56WlgY1tVJPm0VERERERERERCQpVeLK09MTs2bNQmZmplT28OFDfPHFF3yqIBERERERERERlYlSDY9asWIF3NzcYGlpCUdHRwBAQkICTE1NsW3btjINkIiIiIiIiIiIPk6lSlzVrFkTiYmJ2LFjBy5dugQtLS0MGzYM/fv3R5UqVco6RiIiIiIiIiIi+giVekIqHR0djBo1qixjISIiIiIiIiIikpQ6cXX9+nVEREQgIyMDcrlcYdmcOXPeOjAiIiIiIiIiIvq4lSpxtWnTJowdOxYmJiaoUaMGZDKZtEwmkzFxRUREREREREREb61UiatFixbh66+/xowZM8o6HiIiIiIiIiIiIgCASmlWevDgAXr37l3WsRAREREREREREUlKNeKqd+/eOH78OMaMGVPW8RAREX0QrGYeLu8QqBK5/U2X8g6BiIiIqEIqVeKqXr16mD17Nn7//Xc0btwYVapUUVju5+dXJsEREREREREREdHHq1SJq40bN0JXVxeRkZGIjIxUWCaTyZi4IiIiIiIiIiKit1aqxFVKSkpZx0FERERERERERKSgVJOz58nOzkZycjJycnLKKh4iIiIiIiIiIiIApUxcPX36FCNGjIC2tjYaNWqE1NRUAK/mtvrmm2/KNEAiIiIiIiIiIvo4lSpxNWvWLFy6dAkRERHQ1NSUytu3b4+QkJAyC46IiIiIiIiIiD5epUpc7d+/H2vXrsWnn34KmUwmldvZ2eHWrVslamvdunWoU6cONDU14ezsjDNnzhRYNyIiAjKZLN/rjz/+UKi3d+9e2NnZQUNDA3Z2dti3b1/JdpCIiIiIiIiIiMpdqRJX//77L6pXr56v/MmTJwqJrKKEhIRg8uTJ+PLLLxEfH4/WrVujU6dO0q2HBUlOTkZaWpr0ql+/vrQsOjoaffv2ha+vLy5dugRfX1/06dMH58+fL/4OEhERERERERFRuStV4qpZs2Y4fPiw9D4vWbVp0ya4uroWu52VK1dixIgR+Pzzz2Fra4vAwEBYWFhg/fr1ha5XvXp11KhRQ3qpqqpKywIDA+Hp6YlZs2ahYcOGmDVrFtq1a4fAwMCS7SQREREREREREZUrtdKstGTJEnTs2BHXrl1DTk4OVq9ejatXryI6OhqRkZHFaiM7OxtxcXGYOXOmQnmHDh0QFRVV6LqOjo54/vw57Ozs8NVXX6FNmzbSsujoaEyZMkWhvpeXFxNXRERERERERESVTKlGXLVs2RLnzp3D06dPUbduXRw/fhympqaIjo6Gs7Nzsdq4d+8ecnNzYWpqqlBuamqK9PR0peuYmZlh48aN2Lt3L0JDQ9GgQQO0a9cOp0+fluqkp6eXqE0AePHiBbKyshReRERERERERERUvko14goAGjdujC1btrx1AG/OiSWEKHCerAYNGqBBgwbSe1dXV9y5cwfLly+Hm5tbqdoEXo0gmz9/fmnCJyIiIiIiIiKid6RUiauiJk+vXbt2kW2YmJhAVVU130iojIyMfCOmCtOiRQts375del+jRo0Stzlr1iz4+/tL77OysmBhYVHsGIiIiIiIiIiIqOyVKnFlZWVV6Aim3NzcIttQV1eHs7MzwsPD0aNHD6k8PDwcPj4+xY4lPj4eZmZm0ntXV1eEh4crzHN1/PhxtGzZssA2NDQ0oKGhUextEhERERERERHRu1eqxFV8fLzC+5cvXyI+Ph4rV67E119/Xex2/P394evrCxcXF7i6umLjxo1ITU3FmDFjALwaCXX37l1s3boVwKsnBlpZWaFRo0bIzs7G9u3bsXfvXuzdu1dqc9KkSXBzc8PSpUvh4+ODX3/9FSdOnMDZs2dLs6tERERERERERFROSpW4atq0ab4yFxcXmJub49tvv0XPnj2L1U7fvn1x//59LFiwAGlpabC3t0dYWBgsLS0BAGlpaQq3JWZnZ2PatGm4e/cutLS00KhRIxw+fBidO3eW6rRs2RK7d+/GV199hdmzZ6Nu3boICQlB8+bNS7OrRERERERERERUTmRCCFFWjd24cQMODg548uRJWTVZLrKysmBgYIDMzEzo6+uXdzhvzWrm4fIOgSqR2990Ke8QiD4I7HupJNj3Er099rtUUux7icpXcXMvpRpxlZWVpfBeCIG0tDTMmzcP9evXL02TRERERERERERECkqVuKpatWq+ydmFELCwsMDu3bvLJDAiIiIiIiIiIvq4lSpxderUKYX3KioqqFatGurVqwc1tVI1SUREREREREREpKBUWSZ3d/eyjoOIiIiIiIiIiEhBsRNXBw4cKHaj3bp1K1UwREREREREREREeYqduOrevXux6slkMuTm5pY2HiIiIiIiIiIiIgAlSFzJ5fJ3GQcREREREREREZECleJWNDIywv379wEAw4cPx6NHj95ZUERERERERERERMVOXGVnZyMzMxMAsGXLFjx//vydBUVERERERERERFTsWwVdXV3RvXt3ODs7QwgBPz8/aGlpKa37008/lVmARERERERERET0cSp24mr79u1YtWoVbt26BZlMhszMTI66IiIiIiIiIiKid6bYiStTU1N88803AIA6depg27ZtMDY2fmeBERERERERERHRx63YiavXpaSklHUcRERERERERERECkqVuAKAkydP4uTJk8jIyIBcLldYxjmuiIiIiIiIiIjobZUqcTV//nwsWLAALi4uMDMzg0wmK+u4iIiIiIiIiIjoI1eqxNUPP/yA4OBg+Pr6lnU8REREREREREREAACV0qyUnZ2Nli1blnUsREREREREREREklIlrj7//HPs3LmzrGMhIiIiIiIiIiKSlOpWwefPn2Pjxo04ceIEmjRpgipVqigsX7lyZZkER0REREREREREH69SJa4SExPh4OAAALhy5UpZxkNERERERERERASglImrU6dOlXUcRERERERERERECkqUuOrZs2eRdWQyGfbu3VvqgIiIiIiIiIiIiIASJq4MDAzeVRxEREREREREREQKSpS4CgoKeldxEBERERERERERKVAp7wCIiIiIiIiIiIiUYeKKiIiIiIiIiIgqJCauiIiIiIiIiIioQmLiioiIiIiIiIiIKqRyT1ytW7cOderUgaamJpydnXHmzJkC64aGhsLT0xPVqlWDvr4+XF1dcezYMYU6wcHBkMlk+V7Pnz9/17tCRERERERERERlqFwTVyEhIZg8eTK+/PJLxMfHo3Xr1ujUqRNSU1OV1j99+jQ8PT0RFhaGuLg4tGnTBt7e3oiPj1eop6+vj7S0NIWXpqbm+9glIiIiIiIiIiIqI2rlufGVK1dixIgR+PzzzwEAgYGBOHbsGNavX48lS5bkqx8YGKjwfvHixfj1119x8OBBODo6SuUymQw1atR4p7ETEREREREREdG7VW4jrrKzsxEXF4cOHToolHfo0AFRUVHFakMul+PRo0cwMjJSKH/8+DEsLS1Rq1YtdO3aNd+IrDe9ePECWVlZCi8iIiIiIiIiIipf5Za4unfvHnJzc2Fq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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.rcParams['font.size'] = 10\n", + "\n", + "new_attr = llm_attr.LLMAttributionResult(tokenizer, attr.attribution_matrix, attr.prompt_tokens, attr.generation_tokens, attr.all_tokens)\n", + "new_attr.compute_sentence_attr(norm = False)\n", + "\n", + "# new_attr.plot_attr_table_sentence()\n", + "\n", + "og = new_attr.sentence_attr.clone()\n", + "\n", + "thresh = 0.25\n", + "new_attr.draw_graph(cmap = plt.cm.Blues, wrap_width=18, thresh = thresh, spacing = 3.2, arrow_mod=0.3, rad = 0.3)\n", + "\n", + "new_attr.sentence_attr = attrs[1]\n", + "new_attr.plot_context_attr_sentence(\"Row Attribution\")\n", + "\n", + "new_attr.sentence_attr = attrs[2]\n", + "new_attr.plot_context_attr_sentence(\"CAGE Attribution\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABf8AAALbCAYAAABE/fqBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAA9hAAAPYQGoP6dpAAC4j0lEQVR4nOzdd3hUZf7+8fvMpNESUoDQe6QqIBpklQ4WQBEMq4EVJWKhRkVXBIGfCAGVIEUpAgqiSDOyiLoEF1gRRURhCbguHem71IApZOb5/cE3s0RwJZCcyUzer+s6l8k5JzOfuRkH8jnPeR7LGGMEAAAAAAAAAAD8hsPbBQAAAAAAAAAAgIJF8x8AAAAAAAAAAD9D8x8AAAAAAAAAAD9D8x8AAAAAAAAAAD9D8x8AAAAAAAAAAD9D8x8AAAAAAAAAAD9D8x8AAAAAAAAAAD9D8x8AAAAAAAAAAD9D8x8AAAAAAAAAAD9D8x8AAAAAAAAAAD9D8x8AAMCLjDHeLgEAAAAA4Ido/gM+5NcNIhpG9iNze7ndbm+XUGycPHmS97fN9u3bp19++UWWZZE9AAAAAKDA0fzHdcnJyfF2CcWKy+XSyZMnderUKV24cIGGkQ3Onz+vn3/+WVu3bqVJZ5O5c+dq/PjxkiSHw8EFABskJyerT58+OnTokLdLKTYWL16snj17qn379srMzJRlWd4uCQAAAADgZ2j+45qsWbNGkhQQEMAFAJusXLlSvXv3Vp06ddSkSRN16NBBu3btohldiFasWKGePXsqJiZGTZs21a233qodO3bIsiwa0oXkvffe02OPPaYXX3xRU6ZMkcQFgML25ptvaujQoQoMDPR2KcXGzJkz9cgjj6h06dLq06ePQkJCvF0SAAAAAMAP0fxHvs2dO1ft27fX/fffL4kLAHaYMWOGevTooVWrVqlq1aoKCgrSl19+qbvuukuHDh1ixGghmDlzpv70pz/pn//8p3r16qWOHTtqx44deuCBB5SRkSGHg4/PwvD3v/9dkmRZlhITEzV16lRJXAAoLNOmTdOgQYPUu3dvvfLKK6pSpYqkvNMtcXGxYH388ccaMmSI7rvvPk2YMEFPPvmkt0sCAAAAAPgpulfIl88//1wDBgyQJC1fvlwPPfSQJC4AFKaFCxfq6aefVpcuXbR8+XJt2bJF3333nTp16qQ9e/bo5ZdfpjlXwN577z0NGjRInTp10vvvv6/Zs2drxYoVuu+++/TPf/5Te/fu9ZxL9gUjt9kcGxurli1bekb9DxkyRNOmTZN08QIAnzMF56233tLgwYPVq1cvPf/882rQoIHnWHZ2tqSLU41xcbFgGGOUkZGhOXPmqFatWkpMTNQtt9ziOb5t2zZ9+eWX+umnn3TixAkvVgoAAAAA8Bc0/3HVdu7cqQkTJsgYo9dff1033nijFi1apAcffFASFwAKQ1pampKSkhQbG6vhw4frjjvukCSFhYVp5syZqlChgnbu3ElzrgCtX79eo0aNUseOHTVs2DC1aNFCbrdbQUFBuu2222RZlsLCwnT06FGlp6eTfQHJvZOiQYMG2rBhg+6++26tXLlSkjR48GDPBYCAgACv1ehPZs6cqYEDB6p79+4aMWKEGjVqJEk6fvy45s+fr7i4ON133316+OGH9cMPP+iXX37xcsW+z7IsnT9/Xl988YU6d+6s2NhYSdKGDRvUr18/3XTTTWrdurWaNm2qBx98UKtWrfJyxQAAAAAAX0fzH1fFGKOtW7dq3bp1GjRokJ555hktXrxYDRs21OLFi7kAUAiMMVq1apXS0tL02GOPqWnTppLkmeM/NDRUZcuW1U8//aSjR496uVr/kJGRodTUVJ08eVJPPfWUJ3OHw6Fdu3ZpyZIlCgsL09ChQ3XjjTeqefPmmjx5svbt2+fdwv2E2+1W9erVFRoaqq+++kp33323Fi9eLOniBYCZM2dKkuLi4jR79mxvlurT/vOf/+jTTz+VJJUvX14VK1aUJK1bt059+/bVI488opUrV2rVqlVauHCh7rnnHs2dO1dnz571Ztl+4fTp08rMzFS5cuUkSZs3b9bzzz+v9957T/Hx8erdu7eaNGmiL774Qr169dJnn33m5YoBAAAAAL6M5j+uimVZqlWrll599VU9//zzkqSYmBgtXbqUCwCFxLIs7dy5U7fccot69+4t6b9TzFiWpfDwcNWsWVOWZTH/fAEpUaKEateureTkZHXp0sWz/+eff9aUKVO0efNm3XrrrapYsaJ69Oghl8ul4cOHa/78+XK73UwBdJ0cDocqV66smjVrKjU1VW63Ww888IAWLVokSXrqqad02223admyZdqwYYPS09O9XLFvioqK0ogRI3T//fdr9uzZmjhxotasWaPRo0friy++0JQpU/Tl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uXOnl6sEAAAAAAAAANjOiwv+BgcHKzQ0NM/2e83//fv3a/Xq1Xrsscc8+6KjoyXpshH8x48f99wNEB0drezsbJ06deo3z7laXm/+565QbIzR9u3bNWfOHCUkJOjTTz/VypUr9dlnn6lv376aM2eOxo0bp3/9619erhgAAAAAAAAAgN/2zjvvqHz58urcubNnX82aNRUdHa3U1FTPvuzsbK1bt04tW7aUJN18880KDAzMc86RI0eUlpbmOedqeX3aH6fTKUk6cOCAypQpozNnzujRRx9VvXr1JEmxsbGKiopSUFCQZs6cKenibRYxMTGSru12BwAAAAAAAACAD7G8Po79qrndbr3zzjvq06ePAgL+24K3LEuJiYkaN26c6tatq7p162rcuHEqWbKk4uPjJUlhYWFKSEjQs88+q8jISEVERGjo0KFq3LixOnTokK86vN78ly7O8Z+YmKi77rpLzZs391zBcLlccjqdql27toYOHSpJngsAL774ourWrUvjHwAAAAAAAABQZKxevVoHDhxQ3759Lzv2/PPPKyMjQ/3799epU6cUGxurVatWqUyZMp5zJk2apICAAPXs2VMZGRlq37693n33Xc9A+qtVJJr/UVFRqly5sr744gtVrVpVR48eVXR0tGcdAEmqVauW5wLA3LlzlZ6ervHjx6tOnTreKhsAAAAAAAAAgDw6deokY8wVj1mWpdGjR2v06NG/+fMhISGaOnWqpk6del11ePVeidwA4uPjlZycrKpVq2rPnj1asmSJpItBXBpSrVq19NxzzykuLk5r1qxRqVKlvFI3AAAAAAAAAMBGDst7m4+ytfnvdrvzfH/plD1xcXFKSkpS5cqVNWTIEL333nuecy69AFCzZk2NGTNG27dvV8WKFQut1qysLJ09ezbPdiE7q9CeDwAAAAAAAACAgmJb89/tdnum8dm9e7fWr1+v1atXa/v27Z5z4uLilJycrEqVKqlPnz6/eQGgRo0aio6OLtR6k5KSFBYWlmf7bN5bhfqcAAAAAAAAAIArsBze23yULXP+X9r4nzhxoqZOnaoDBw54jg8cOFAPP/ywmjdvrri4ODkcDg0ZMkR9+vSRJP3pT3/yXACwa4HfYcOG6Zlnnsmzb8HWo7Y8NwAAAAAAAAAA18OW5n9u43/cuHEaMWKEOnXqpLFjxyooKEiffvqpZs2apa1b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AAAAAIAiy+HtAnJd2vifMmWK7r77bjVv3lyxsbF68803deTIkat+rIYNG9L4BwAAAAAAAAAUW0Wm+Z/b+E9KSlJiYqKysrLUrFkzZWdna9CgQRo1apR27tzp5SoBAAAAAAAAALazvLjl06FDh9S7d29FRkaqZMmSatKkiTZv3uw5bozR6NGjValSJZUoUUJt2rTR9u3b8zxGVlaWBg0apKioKJUqVUr33nuvDh48mK86vN78d7lcki6+4O3bt2vOnDlKSEjQp59+qpUrV+qzzz5T3759NWfOHI0bN07/+te/vFwxAAAAAAAAAACXO3XqlP7whz8oMDBQn332mXbs2KGJEyeqbNmynnNeffVVJScna9q0adq0aZOio6PVsWNHpaene85JTExUSkqKPvzwQ61fv17nzp1Tly5dPP30q+H1Of+dTqck6cCBAypTpozOnDmjRx99VPXq1ZMkxcbGKioqSkFBQZo5c6YkadiwYYqJiZGka14YGAAAAAAAAADgG3ylBzxhwgRVrVpV77zzjmdfjRo1PF8bY/TGG29o+PDh6t69uyRp3rx5qlChgj744AM98cQTOnPmjObMmaP33ntPHTp0kCQtWLBAVatW1erVq3XnnXdeVS1eH/kvXZzjv2bNmnryySfVvHlztWzZUtJ/7wqoXbu2hg4dqieeeELz589XUlKSZwogX/lDBwAAAAAAAAD4t7/85S9q3ry54uLiVL58eTVt2lRvv/225/jevXt19OhRderUybMvODhYrVu31oYNGyRJmzdv1oULF/KcU6lSJTVq1MhzztXw+sh/SYqKilLlypX1xRdfqGrVqjp69Kiio6M96wBIUq1atTR06FBJ0ty5c5Wenq7x48erTp063iobAAAAAAAAAODnsrKylJWVlWdfcHCwgoODLzt3z549mj59up555hm9+OKL+vbbbzV48GAFBwfr4Ycf1tGjRyVJFSpUyPNzFSpU0P79+yVJR48eVVBQkMLDwy87J/fnr4ZXR/4bYyRJ8fHxSk5OVtWqVbVnzx4tWbJE0sVR/bnnSBcvADz33HOKi4vTmjVrVKpUKa/UDQAAAAAAAACwj2VZXtuSkpIUFhaWZ0tKSrpinW63W82aNdO4cePUtGlTPfHEE+rXr5+mT59+2eu51NVMb5/fKfBtbf673e48319aaFxcnJKSklS5cmUNGTJE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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAE5IAAASSCAYAAABtIBVXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAC4jAAAuIwF4pT92AAEAAElEQVR4nOzcQQ0AIBDAMMC/50MDL7KkVTAF2zMzCwAAAAAAAAAAAAAAAAAAAAAAAICM8zsAAAAAAAAAAAAAAAAAAAAAAAAAgDdGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAAAxRnIAAAAAAAAAAAAAAAAAAAAAAAAAMUZyAAAAAAAAAAAAAAAAAAAAAAAAADFGcgAAAAAAAAAAAAAAAAAAAAAAAACXvfsOr6q+Hzj+CUkIYW9QFAcICIp777131Wrrtm5r1VZb69aqVevWauve1r333htRAUFAGcreEEbG7w9+otebhNxLkpt77+v1PD4++d57Tj4EeBvhnO/JMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAAAAAAAAAAAAAAAAAAAMgyNpIDAAAAAAAAAAAAAAAAAAAAAAAAyDI2kgMAAAAAAAAAAAAAAAAAAAAAAADIMjaSAwAAAAAA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AAAAmBHJAQAAAAAAAAAAAAAAAAAAAAAAAMyI5AAAAAAAAAAAAAAAAAAAAAAAAABmRHIAAAAAAAAAAAAAAAAAAAAAAAAAMyI5AAAAAAAAAAAAAAAAAAAAAAAAgBmRHAAAAAAAAAAAAAAAAAAAAAAAAMCMSA4AAAAAAAAAAAAAAAAAAAAAAABgRiQHAAAAAAAAAAAAAAAAAAAAAAAAMCOSAwAAAAAAAAAAAAAAAAAAAAAAAJgRyQEAAAAAAAAAAAAAAAAAAAAAAADMiOQAAAAAAAAAAAAAAAAAAAAAAAAAZkRyAAAAAAAAAAAAAAAAAAAAAAAAADMiOQAAAAAAAAAAAAAAAAAAAAAAAIAZkRwAAAAAAAAAAAAAAAAAAAAAAADAjEgOAAAAAAAAAAAAAAAAAAAAAAAAYEYkBwAAAAAAAAAAAAAAAAAAAAAAADAjkgMAAAAAAAAAAAAAAAAAAAAAAACYEckBAAAAAAAAAAAAAAAAAAAAAAAAzIjkAAAAAAAAAAAAAAAAAAAAAAAAAGZEcgAAAAAAAAAAAAAAAAAAAAAAAAAzIjkAAAAAAAAAAAAAAAAAAAAAAACAGZEcAAAAAAAAAAAAAAAAAAAAAAAAwIxIDgAAAAAAAAAAAAAAAAAAAAAAAGBGJAcAAAAAAAAAAAAAAAAAAAAAAAAwI5IDAAAAAAAAAAAAAAAAAAAAAAAAmBHJAQAAAAAAAAAAAAAAAAAAAAAAAMyI5AAAAAAAAAAAAAAAAAAAAAAAAABmRHIAAAAAAAAAAAAAAAAAAAAAAAAAMyI5AAAAAAAAAAAAAAAAAAAAAAAAgBmRHAAAAAAAAAAAAAAAAAAAAAAAAMCMSA4AAAAAAAAAAAAAAAAAAAAAAABgRiQHAAAAAAAAAAAAAAAAAAAAAAAAMCOSAwAAAAAAAAAAAAAAAAAAAAAAAJgRyQEAAAAAAAAAAAAAAAAAAAAAAADMiOQAAAAAAAAAAAAAAAAAAAAAAAAAZkRyAAAAAAAAAAAAAAAAAAAAAAAAADMiOQAAAAAAAAAAAAAAAAAAAAAAAIAZkRwAAAAAAAAAAAAAAAAAAAAAAADAjEgOAAAAAAAAAAAAAAAAAAAAAAAAYEYkBwAAAAAAAAAAAAAAAAAAAAAAADAjkgMAAAAAAAAAAAAAAAAAAAAAAACYEckBAAAAAAAAAAAAAAAAAAAAAAAAzIjkAAAAAAAAAAAAAAAAAAAAAAAAAGZEcgAAAAAAAAAAAAAAAAAAAAAAAAAzIjkAAAAAAAAAAAAAAAAAAAAAAACAGZEcAAAAAAAAAAAAAAAAAAAAAAAAwIxIDgAAAAAAAAAAAAAAAAAAAAAAAGBGJAcAAAAAAAAAAAAAAAAAAAAAAAAwI5IDAAAAAAAAAAAAAAAAAAAAAAAAmBHJAQAAAAAAAAAAAAAAAAAAAAAAAMyI5AAAAAAAAAAAAAAAAAAAAAAAAABmRHIAAAAAAAAAAAAAAAAAAAAAAAAAMyI5AAAAAAAAAAAAAAAAAAAAAAAAgBmRHAAAAAAAAAAAAAAAAAAAAAAAAMCMSA4AAAAAAAAAAAAAAAAAAAAAAABgRiQHAAAAAAAAAAAAAAAAAAAAAAAAMCOSAwAAAAAAAAAAAAAAAAAAAAAAAJgRyQEAAAAAAAAAAAAAAAAAAAAAAADMiOQAAAAAAAAAAAAAAAAAAAAAAAAAZkRyAAAAAAAAAAAAAAAAAAAAAAAAADMiOQAAAAAAAAAAAAAAAAAAAAAAAIAZkRwAAAAAAAAAAAAAAAAAAAAAAADAjEgOAAAAAAAAAAAAAAAAAAAAAAAAYEYkBwAAAAAAAAAAAAAAAAAAAAAAADAjkgMAAAAAAAAAAAAAAAAAAAAAAACYEckBAAAAAAAAAAAAAAAAAAAAAAAAzIjkAAAAAAAAAAAAAAAAAAAAAAAAAGZEcgAAAAAAAAAAAAAAAAAAAAAAAAAzIjkAAAAAAAAAAAAAAAAAAAAAAACAGZEcAAAAAAAAAAAAAAAAAAAAAAAAwIxIDgAAAAAAAAAAAAAAAAAAAAAAAGBGJAcAAAAAAAAAAAAAAAAAAAAAAAAwI5IDAAAAAAAAAAAAAAAAAAAAAAAAmBHJAQAAAAAAAAAAAAAAAAAAAAAAAMyI5AAAAAAAAAAAAAAAAAAAAAAAAABmAmp5DqqjZIjhAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABIgAAAEECAYAAABDZg/HAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAA9hAAAPYQGoP6dpAABIa0lEQVR4nO3deVhV5f7//9cGZBAUFIfkSJqzpqkhaJoimJp6tNSjpZVaWlZ2muxY6Te1TqV2slNnSjsqNDhlOaWWJaHmlENOp9SOM2oexUxQJpH1+4Mf67MRNrBhwd5bno/r2te19l7vdd/33rzZxdv7vpfNMAxDAAAAAAAAqLS8XD0AAAAAAAAAuBYFIgAAAAAAgEqOAhEAAAAAAEAlR4EIAAAAAACgkqNABAAAAAAAUMlRIAIAAAAAAKjkKBABAAAAAABUchSIAAAAAAAAKjkKRAAAAAAAAJUcBSIAAIBKpmHDhrLZbLLZbDp+/HihMd27dzdj1q9fX6HjK2/r168331v37t1dPRwAANwCBSIAADyY/R/xhT2qVaumm2++WX369NGbb76p06dPu3rIHuGll17K9zk+/fTTrh4SAABAuaJABADADezy5ctKSkrSV199pUmTJumWW27Ra6+9JsMwXD00t5WTk6P58+fne23BggW6evVqidsYNWqUWVyKj48vt2vAbCAAAKzi4+oBAAAAa0RGRioqKirfa5cuXdLevXu1f/9+SdLVq1c1ZcoU/fbbb3rnnXdcMUy3l5CQoFOnTuV77cKFC1q9erXuvfde1wwKAACgnFEgAgDgBtG3b19NnTq10HNbtmzR/fffr6SkJEnSX//6Vw0fPlwdOnSowBF6hg8//NA89vf3V0ZGhvn6jVIgcrTvUGXRvXt3ZtEBAHAdlpgBAFAJdO7cWStWrJDNZjNf++CDD1w4IveUmpqqZcuWmc/ffvtt83j16tVKTk52xbAAAADKHQUiAAAqifbt2ys6Otp8vnHjRheOxj0tWbJEaWlpkqTGjRtr3LhxuvXWWyXlLs9buHChK4cHAABQbigQAQBQibRv3948PnPmTLHxhmFoyZIlGjZsmBo3bqygoCAFBQWpcePGGj58uD777LMil+ps27bN3EC4a9euDuPS0tLk6+tbotiMjAz5+/vLZrMpMDDQqc2ji2O/vOzBBx+UJD300EOFni9M3u3j7eMefvjhQu8wl7ccsDTX5CnsVvS//PKL3nzzTUVFRemmm26St7e3QkJCCh1nUbe5L8ypU6c0efJktWvXTjVr1lRgYKBatGihZ555Rj///HOx1zu7EXd8fLwZP2rUqHznpk6dKpvNppiYGPO1DRs2FPq5NWzYMN+1pdnYeu3atXrkkUfUrFkzVa9eXQEBAWrQoIEGDhyouLi4EuVhYe//ypUr+te//qU777xTdevWlZ+fn8LDwzVs2DBt3ry5RGMDAMAK7EEEAEAlEhAQYB7n7a3jyH//+1/dd9992r17d4FzR48e1dGjR7Vw4UJFRERo8eLFaty4cYG4Dh06KCgoSJcvX9b333+vtLQ0Va1atUDc5s2b8/2BXVTs1q1blZmZKSl36VyVKlWKfB8ldezYMX333Xfm87wC0QMPPKCJEycqJydHu3bt0o8//mjOKnI3K1as0MMPP6yLFy9a3vYXX3yhESNG6Lfffsv3+qFDh3To0CHNnj1bb7/9tp566inL+3alc+fOafjw4UpISChw7uTJkzp58qSWL1+uadOmacGCBU7t63XgwAENHjxYBw4cyPf6qVOntGjRIi1atEiTJ0/Wq6++Wub3AQBAcSgQAQBQidjPGqpTp47DuAMHDig6Olrnz583X2vTpo3atWsnm82m3bt3m3dG27Vrl7p06aKNGzeqWbNm+drx8fFRly5dtHbtWl29elWbN29Wz549C/SXN/slT0ljrbyt+UcffWTOhrrjjjvUpEkTSVL9+vUVExNjFgg+/PBDvfXWW4W2MXLkSF24cEEJCQk6ePCgJKlHjx5q0aJFgdi8O86V5prCbNmyRVOnTtXVq1cVGhqqbt26qVatWjp37lyhRT5n7Ny5U5MmTVJWVpZq1qyp7t27q2bNmjp58qTWr1+vrKwsZWZm6o9//KO8vLz05JNPlqm/koiKitK4ceN0+vRpLV++XJIUFhamgQMHFogNDQ0tVR//+9//1KVLFx05csR8rXHjxurYsaP8/Pz0008/6fvvv5eUW1CNiYnRV199pS5duhTb9pkzZ3TXXXfpzJkzCgkJUdeuXXXTTTcpOTlZ3377rS5duiRJeu2119SqVSvdd999pXoPAACUmAEAADxWdHS0IcmQZEyZMqXI2KtXrxrh4eFm/ODBgwuNy8zMNNq2bWvG1a5d21i7dm2BuLVr1xq1atUy426//XYjKyurQNy0adPMmJdffrnQPjt37mz2VVxs165dzZhNmzYV+Z6d0bhxY7Pdf/7zn/nOxcfHm+fCwsKM7OzsItsaOXKkGR8XF1ei/ktzjf3P38fHx7DZbMaf//znAj+HjIyMfM8bNGhgXnfs2LFi2/b19TUkGc8//3yBtk6fPm3ExsaasX5+fsaBAwcseY9xcXFm/MiRIwuNSUxMNGOio6OLbdOZa/r06WPGVa1a1Zg/f36BmB07dhiNGjUy48LDw42LFy8W2p79+/fz8zMkGRMmTDCuXLmSL+7ChQv5PtNGjRoZOTk5JXpvAACUFnsQAQBQSbzxxhvmbe4l6bHHHis0bv78+dq7d68kqUqVKvryyy/Vq1evAnG9evXSmjVr5OOTOyH5hx9+KHQTZ/s9Yq6fKSTl7j+0Y8cOSVL//v3NmTOFxaanp2v79u2SpKpVqxY5o8YZmzZtMmeJVKlSpcBsjcGDB5vL3c6cOaN169ZZ0q+VsrOz9ec//1n/7//9vwLL7vz8/MrUdlZWlh5//HHNnDmzQFthYWFatWqVbrvtNklSZmamJk+eXKb+3EFiYqK+/PJL8/nChQs1fPjwAnEdOnRQQkKCgoODJUlJSUn629/+Vmz7mZmZevnllzVjxowCSylr1qypBQsWKDAwUFLuks68vAcAoLxQIAIA4AaWkpKijRs3atiwYfk2OH722WcLLfpI0uzZs83jxx9/XBEREQ7bj4yM1KOPPmo+f//99wvEREREqFq1apKkHTt26PLly/nOb9q0ydx/qHv37mZBqbDYLVu2mPsPdenSxbL9h+w3iO7bt2+BJUlBQUH5li4Vt1m1K/zud7/Tiy++WC5tV6tWTTNmzHB4PiAgQDNnzjSfL1++XMnJyeUylopi/3vQv39/DRgwwGFsw4YNNXHiRPP5rFmzity8XZJq165dZCGtbt266tevn/k8r4gKAEB5oUAEAMAN4tVXXy1w96bg4GBFR0dr0aJFknL3YpkxY4b++te/FtrG5cuXtXPnTvP5I488Umy/Y8aMMY937NihK1eu5Duftw+RlDvLZdOmTfnO288UiomJMfcVKi7Wqv2H0tPTtWTJEvN53ubU17O/m9ny5cuVkpJiSf9WGTx4sDmby2r33HOPqlevXmRMjx49VL9+fUm5e0hd/7PzNImJieZxSX4PHn74YXl55f6v9S+//KJDhw4VGd+/f3/5+/sXGWN/10Fn7jYHAEBpUCACAKCS8Pb21owZMzRhwgSHMXv37tW1a9ck5c6ayVs2VJR27dqZS2GuXbtmLk+zZ1/Msf/DW/q/ok+TJk1Uv379ImPtn1tVIFq+fLm5IXBISIj69+9faNxdd92levXqScotKn366aeW9G+VomZ6lVWnTp2KjbHZbOrYsaP5vKwbY7vS6dOnde7cOfN5586di72mdu3a+TZp/+GHH4qMb9OmTbFt2s9ky8tRAADKCwUiAABuEJGRkRo3bpz5GDlypGJiYsw9Y65du6YxY8Zo0qRJDtuwv2tZeHi4OSOiKF5eXgoPDzefF7a0yL6YYz8L6MqVK+aMpbyYOnXqqFWrVgVi7fcqCgwMVGRkZLFjKwn75WJDhgxxuF+Pt7d3vj1o3G2ZWe3atcut7ZtvvrlEcfZ5YJ9LnsZ+7AEBAUXe8c9ew4YNzePiltjl7VlUFPsllHnLMAEAKC8UiAAAuEH07dtX//jHP8xHfHy8vv32Wx0/flzDhg0z4958800tXry40Dbs9/zJmxVUEvaxqampBc536NDB3Ido165d5vKszZs3m3/42m9mnVcsuj42KytLknX7D12/4bSj5WV57JeZ2W9s7Q4CAgLKre3rN1F2pLg88BTl9Xtgz2azOT8wAADKEQUiAABucDfddJM++eQT9e7d23ztySef1MWLFwvEBgUFmcfX7yVUFPvYvEKQPW9vb915552Scmcyfffdd5IcLxnLKxbZx5bH/kOffPKJuaROkqKjowvs42T/aNeuXb7rP/roI0vG4e7S0tJKFFdcHjgrJyenzG2URnn9HgAA4M4oEAEAUAl4eXlpzpw55gyHX3/9VW+++WaBOPtlSklJScXeiUnK/SM+KSnJfF6rVq1C4wrbWyiv6NO8eXOFhYXli82bYZEXWx77D5W1wPPxxx+X6DPydCdPnnQ6rrA8sJ/1lZ2dXWx7rtp3x/73ID09vcR3ZDtx4oR57Oj3AAAAd0WBCACASqJ+/fp69tlnzef/+Mc/dPbs2Xwxbdu2lbe3t6TcZTb79+8vtt29e/eaMye8vb3Vtm3bQuOu34eosP2H8tSqVUu33nprobFW7T+0a9cu/fjjj+bzqKgodezYsUSPvL2Zjh07Zs5wslea5UPuvORo69atxcYYhqHvv//efH777bcXiLGfVXPhwoVi2yxJ/pXH5/a73/0u375DW7ZsKfaaCxcu5LtzWWHvHwAAd0aBCACASmT8+PHmH+kZGRn6y1/+ku98UFCQOnToYD6Pj48vts24uDjzOCoqyuGeLREREeat0nfv3q1Vq1aZs0js9x/Kk1c0yovN26uoS5cultzO3X6T6fbt2+v777/Xtm3bSvSIjY0ttJ089rcvL+nmwqW5pqKsXLmy2Nk869at0+nTpyXlzhTq0qVLgZhbbrnFPN6zZ0+R7WVkZOiLL74odmzl9bnZ52RJfg8+/PBDc0lcWFiYmjdvbtlYAACoCBSIAACoRGrUqKE//vGP5vNZs2YVWD4zduxY8/if//yn9u3b57C93bt3a9asWebzxx9/3GGs/T5EOTk5ev31181zhS0Zy/sD/frYwopJzrp69aoWLlxoPn/ggQecut5+M+slS5YU2KPH/vbkeUWT4pTmmoqSmpqql156yeH59PR0vfDCC+bze+65p9C7qkVFRZnHq1atKnLp1uTJk0u0tKu8Pjf734Nly5bpq6++chiblJSUL0fHjh3r1jPCAAAoDAUiAAAqmeeff97chDctLU3vvPNOvvMPPPCAuUwsKytLvXv3zrf/T56EhATdfffd5qyN22+/Pd/d0gpjXwj6z3/+I0lq2bKl6tatWyA2b8No+9jr2yit1atXm8UHLy8v3X///U5dP2jQIPOuYampqVq2bFm+823atDGPly9fbt59rSiluaai+Pr6atasWXrhhReUmZmZ79wvv/yi/v37m4VEX19fvfrqq4W2ExUVpcaNG0vKXcI4bNiwApulp6WlacKECfrLX/4iPz+/YsfWqFEjc9baiRMntH37dqffX2FiYmLUp08f8/mQIUO0ZMmSAnG7d+9Wjx49zPcRHh6up59+2pIxAABQkco+PxsAAHiU0NBQjRs3TjNmzJCUuxfRn/70J9WoUUNS7h/4CxcuVHR0tM6fP6+zZ88qNjZWbdu2Ne/itWfPHu3du9dss06dOlq4cGGxt54vaqZQYeNs06ZNvhlM1y+BKy37ZWHR0dH63e9+59T11apVU//+/fXpp5+a7dnPQurTp4+qVq2qtLQ07d27Vy1btlT37t0VEhJiFr169eqlXr16lemaivLGG29o0qRJmjlzpuLi4hQbG6saNWro5MmTWr9+fb6i0V/+8he1atWq0HZsNpum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AABQASwrED366KOKiYnRRx99pIULF1rVLAAAAAAAAMqZZXcxS0pK0t///nc99thjevDBB7Vs2TINHz5cLVq0UNWqVYu9nr2LAAAAAAAAXMOyAlHDhg1ls9kkSYZh6PPPP9fnn39eomttNpuys7OtGgoAAAAAAACcYFmBSMotDBV2DAAAAAAAAPdlWYEoLi7OqqYAAAAAAABQgSwrEI0cOdKqpgAAAAAAAFCBLLuLGQAAAAAAADwTBSIAAAAAAIBKztJNqvPk5ORo/fr12rp1q86ePau0tDS9/vrrqlevnhmTlZWl7OxseXt7y8/PrzyGAQAAAAAAgBKwvEC0evVqPf300zp+/Hi+18ePH5+vQDR37lw99dRTCgoK0pkzZxQYGGj1UAAAAAAAAFACli4xmzNnjgYMGKBjx47JMAyFhoY6vN396NGjFRISosuXL2vZsmVWDgMAAAAAAABOsKxAdPjwYY0bN06SFBsbq59++knnzp1zGO/r66vBgwfLMAx9/fXXZer75MmTeuGFF9SyZUsFBgaqZs2aioqK0ttvv620tLQytT116lTZbLYSPdavX1+mvgAAAAAAAFzBsgLRu+++q6tXr+rWW2/VmjVr1KJFi2Kv6dq1qyRpz549pe539erVuu222zRz5kwdPHhQaWlpunjxonbs2KE//elPuv3223X06NFStw8AAAAAAHCjs2wPooSEBNlsNj377LPy9fUt0TWNGzeWlDsDqDT27t2roUOHKi0tTUFBQXr55ZcVExOj9PR0LVq0SP/+97916NAh9evXTzt27FBQUFCp+smzf//+Is/fcsstZWofAAAAAADAFSwrECUlJUmS2rVrV+Jr8jamLu0ysGeffVZpaWny8fHR119/rTvuuMM8Fxsbq6ZNm2rChAk6ePCg3nnnHU2ePLlU/eRp3bp1ma4HAAAAAABwR5YtMbPZbJLkcFPqwpw/f16SVL16daf727Fjh7nnz+jRo/MVh/KMHz9eLVu2lPR/S+AAAAAAAACQn2UForCwMEnSzz//XOJrNmzYIElq2LCh0/0tX77cPH744YcLjfHy8tKIESMkSRcvXmQTaQAAAAAAgEJYViDq1q2bDMPQggULShSfnJys2bNny2azKTY21un+vvvuO0m5y9QiIiIcxkVHR5vHmzZtcrofAAAAAACAG51lBaLHHntMkrRmzRrF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rVq1chhzzz33aNCgQZKkI0eOaM+ePRU0uopDTroXH5+iJ157e3trwoQJ5vONGzeW95AqHDnp3t577z3t2rVLzZs314svvujq4VQIchLuhpx0L0ePHtX06dMlSaNGjdL48eOLjK9SpUpFDMttUSCCS3Xq1Mk8PnHihHl8/Phx2Ww22Ww2xcfHS5KWLl2qvn37KiwsTD4+PoVumPzFF1/oD3/4g+rXry8/Pz+Fhobqjjvu0PTp03X58mWH44iPjzf7O378uLKysvTOO++oQ4cOCg4OVs2aNdW9e3etXr0633Wpqal666231L59e1WvXl0hISHq2bOnEhISHPa1fv16s6/169crJydH//73v9W5c2fVrFlTgYGBatu2rd58802lp6c7HOurr75qvpbXnv3DEzejdAfkpGflpP1GkUeOHLG8fXdATnpWTgYGBprHGRkZlrfvDshJ98zJEydOaPLkyZKk999/X76+vqVuy9OQk+6Zk5UZOek+OfnBBx/o6tWrstls5nckiuDqKUy4MZVk+qVhGEZ6eroZ16JFC/P1Y8eOma/PmzfPeOihhwrdBNS+nYEDBxa54VhYWJixe/fuQsdhPx127969RseOHR22M3PmTMMwDOPEiRPGrbfeWmiMzWYzPv7442I/m7Vr1xp33323w75atmxpnDlzxuFYi3pYMa23si0xMwxy0t1z8nozZ8402//8888tb788kZM3Zk5OnDjRbP8f//iH5e2XJ3LSs3Oyb9++hiTjoYceMl+rDEvMDIOcdKecZIlZLnLSfXKyUaNGhiQjMjLSfO3atWtGUlKScfToUSMtLc2p9m50FIhQLkr65fn999+bcbGxsebr9l+et912myHJ6Nq1q7FgwQJj586dxrp164w5c+aY8UOHDjXj27Zta3z00UfGjh07jLVr1xoPP/ywuU9JzZo1jVOnThUYh/0XUseOHQ0fHx/jySefNL755htj586dxpw5c4x69eoZkgwvLy9j//79RkREhBEQEGC89NJLxvr1640dO3YY7777rhEcHGxIuXdX+t///lfkZxMZGWlIMnr16mUsW7bM2Llzp7Fs2TKjZ8+eZkz79u3z7Xtx8eJFY//+/cYTTzxhxuzfv7/Aw4r1s5WxQEROundOXm/AgAFmn0XtV+SOyMkbJyfPnz9vbNmyxXjkkUfMzzE0NNS4ePGiJe1X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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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O2rdunVq3bq1UlJS9N///leLFi3SwIEDc+z/+vXrmjlzpoYNG5bpXJUqVbRo0SI1btxYhmFoy5Yt+v3331WpUiVrbg4AUCxQIAIAwEXEx8dn2BA6ICCgwMaaP3++uUlukyZN1KhRowznbTabnnrqKU2ePFnSzeVU2RWI7Jcj5SXmixcvavz48Tm26dy5szp37pxjm3PnzunTTz/Ndbx09913n2UFIvvlZf369ZOHR8a/UlWvXl1t2rTRtm3bJElffvml3n33XUvGtkqLFi2yLA5ZoXr16ho1alS258uXL69JkyaZe+VERETo3XffzfQ9FiUzZ840j0eMGJFlcShdSEiInn32WX322WeSpM8++yzXAlGjRo2yLA6la9iwoUJCQrRz504ZhqE9e/bo0UcfdfAuAADFWdH9f2EAAO4w6TNS0vn6+hbYWF9++aV5/NRTT2XZZsCAAWaBaPv27fr111+z3CvFPu68zB6Kj4/PtbBTrly5XAtEzvLbb79l2Csqp+8vvUA0f/58vfPOO3Jzc50HyD7xxBMF1nf//v1zLfY88cQT5ibWcXFxOnjwYKanpxUVV65c0e7du833zzzzTK7XDB061CwQ7dq1S1evXs3xfz+9e/fOtc9mzZpp586dkmRuoA4AQF65zt9SAAAo5tI3OU535cqVAhknvdgjSW5uburfv3+W7erUqaOQkBDzvX1RyZ593OmbXheG0NBQGYaR51deHk+eF/Pnz1daWpqkm5sc33fffVm269Onj7lU69aikivIaYbL7WrVqlWubXx9fdWwYUPzfVZP/Soq9u/fr9TUVEk376tx48a5XtO0aVOzIJSammouT8vOrbP8shIYGGgeX758Odf2AADYo0AEAICL8PPzyzDr4q+//iqQceyXRz344IMKCgrKtq39shf7ZWn27B/hnpeYq1WrlmUBJzQ0NI934Fz2hbJb926yV6ZMmQxLfOy/d1dQvnz5Auv7nnvuyVO7KlWqmMf2T/4qauxjr1KlSp5mirm5uWW4/7i4uBzb+/v759pniRIlzOMbN27k2h4AAHsUiAAAcCFVq1Y1j3/55RfL+0/fcDpddsuj0j3xxBPmf3TeurF1OvuYz5w5o8TERIuidT3pG05LN/dpym0PH/sCkv3G1q6gZMmSBda3j49PntrZL6lype/GUfaz/RzZpN2R+7fZbI4HBgCAAygQAQDgQh544AHz+Oeff7a8/1WrVmWY5TNo0CDZbLZsX+XLl88wEyGrWTBt27Y1j1NTU7Vnzx7L43YV9vdvGIaqVauW4/fXvXt3s31iYqKWLVvmhKgLX16LhPZLEm9dYpkf6Uv/Cpv9fmGOLLO0+v4BALgdFIgAAHAh4eHh5vHp06f1008/Wdp/dvsI5dXy5csz/Qdwq1at5O3tbb63n6F0J0lOTr7te7vd77+oOHPmjMPtypUrl+m8/ZIp+yf8ZcdZ++7YL9eLiYnJcinmrdLS0hQTE2O+z+r+AQAoTDzFDAAAF9K7d2+NGjXK3I9k+vTpat26tSV9//HHH9qwYYP5vkmTJhkKOzmJjo5WUlKSrl69quXLl2fYm8jb21uDBg0yH/M9f/58vf322xk2zL0TfPvtt7p48aKkm4WL5s2b5+m6lJQUc1ZVVFSUTp06pWrVqmVok5/lQ6685Gj79u3q0qVLjm2uXLmigwcPmu+z+j7tZ9X8+eefuY574MCBXNsUxPfWpEkTubu7KzU1VVeuXNGBAwdy3ah6//79ZrHV3d1dTZo0sTwuAAAcwQwiAABcSMmSJfXiiy+a75cvX67ly5c73M/Vq1czzT5asGCBOQujfPny2r17t3bs2JGnl/1eO1ktM3v99dfl7u4u6eZj7IcNG+ZwzK7O/r4fffTRPH93u3fvVq1atSTdXJY2f/78TH3bF+ryurlwfq4pLIsWLcp1xs+iRYuUnJws6ebsGfsnmqW79957zeN9+/bl2N+5c+f0448/5hpbQXxvvr6+GZ5mN3fu3FyviYiIMI9btGjh0N5FAAAUBApEAAC4mNGjR2eYTTFgwAB9++23eb7+wIEDatmypTZu3Jjhc/sCR9++fTM8MS039ptZR0ZGZlpCVKNGDU2ePNl8v2LFCg0dOjRPy4KKggsXLmj9+vXm+9w2p76VffuslpnZz7Y6e/ZsnvrMzzWF5cSJE5o2bVq25+Pi4jRhwgTz/eDBg7PMxxYtWpjHixYt0vXr17Pt85VXXslTwaegvrfhw4ebx59++qmio6Ozbbt3717NmDHDfD9ixAjL4gAAIL8oEAEA4GK8vLy0dOlSVahQQZKUlJSk7t27a+DAgTp06FCW1xiGoV27dmnQoEFq2rSp/ve//2U4v2/fvgz/wdq/f3+HYmrXrp35SO7sZsGMHj1avXv3Nt/Pnj1bTZo00eLFi5WUlJRt36dPn9aYMWO0c+dOh2IqTPazr/z8/HJdPnUr+wLRsWPHtG3btgznGzVqZB4vW7YsT3vY5OeawuLp6amxY8dq2rRpmTaO/vXXX9WhQwf9/vvvkm4WbF5//fUs++natau5zOz06dMaOnRoply6ePGiBg4cqK+//lpeXl65xmb/vf3888953i8pN08++aS5TCw5OVmdOnXK8ql/mzdv1sMPP2wWs5o3b65+/fpZEgMAALeDPYgAAHBB1atX188//6yuXbvq4MGDSktL0/z58zV//nxVq1ZNjRs3Vrly5ZSamqrz589r3759+uOPPzL0Yb9/i/3soerVq+v+++93KB6bzaZ+/fpp6tSpkm7OgnnrrbcytVm0aJGqVKmi6dOnS5J++eUX9evXT56engoJCdHdd9+tMmXK6MaNG/rzzz916NAh/frrrxn6qVixYoanuWXn6NGjeuGFFxy6jzFjxujuu+926Bop4/fXq1evPO/dlK5mzZpq0aKFWQSbN2+e2rRpY57v2bOnxowZI8MwtHbtWjVu3FitW7fO8Gf4xBNPZFjGlJ9rCsvUqVP18ssv67XXXtP06dPVrl07+fr66ujRo/rxxx+Vmpoq6ebeO1988YVZDL2Vj4+Pxo0bp9GjR0uSvvrqK23cuFFhYWHy8/NTTEyMtm7dqsTERDVs2FCdOnXKceaSdDO/2rRpo23btunatWtq0qSJHn74YVWqVElubjf/7bRGjRp67rnnHLpnT09PLVq0SKGhobpw4YLOnz+v8PBwNWnSRE2bNpV0s1C7f/9+85oKFSpo0aJFGTbjBgDAaQwAAOCyEhISjEmTJhkBAQGGpDy9mjRpYqxYscLs48aNG0aFChXM83//+9/zFUt0dHSGcX766ads227YsMFo1apVnmOWZFSuXNmYMGGCER8fn22/EyZMcKjPW1979+51+L7379+foY9NmzY53IdhGMa//vUvsw9/f38jKSkpw/m///3vOcYeERGRqU9Hr6latap57uTJk3mO3b7P7Nza98yZMw1PT89sY/Pz8zOWLFmS69ipqanG0KFDc7zPVq1aGTExMRnyY8KECdn2uWfPHsPPzy/b/kJDQzO0j4iIMM8NGjQox3iPHDliNGvWLNdcbN68uXHs2LEc+woNDTXbR0ZG5vpd5fX+AQDICkvMAABwYb6+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pk3T999/L+nmk88AAAAAAADgHJYViPr27asmTZrIMAyNHj1avXr10g8//KAbN26YbVJSUvTDDz+oZ8+eGj16tGw2mxo2bKinnnrKqjAAAAAAAADgIA+rOrLZbFq5cqXatGmj33//Xd98842++eYblShRQmXLlpXNZtOff/5pFowMw1BQUJBWrVolm81mVRgAAAAAAABwkGUziKSbj63fu3evHnvsMUk3i0DJyck6f/68fv/9dyUnJ5tPLuvZs6f++9//mo+6BwAAAAAAgHNYNoMoXYUKFbRy5UodOXJE69at0969exUXFydJKleunJo3b64uXbqoVq1aVg8NAAAAAACAfLC8QJSuTp06qlOnTkF1DwAAAAAAAItYusQMAAAAAAAARQ8FIgAAAAAAgGKuQJaYpaWl6ZdfftGJEyeUkJCg1NTUXK8ZOHBgQYQCAAAAAACAXFhaIEpKStI777yjL774Qn/++Weer7PZbBSIAAAAAAAAnMSyAlFSUpLCw8O1c+dO81H2AAAAAAAAcH2WFYj++c9/6ueff5YkNWzYUC+88IKCg4NVtmxZubmx1REAAAAAAICrsqxAtGTJEklS69at9f3338vT09OqrgEAAAAAAFCALJvac/z4cdlsNo0ePZriEAAAAAAAQBFiWYEovSh0zz33WNUlAAAAAAAACoFlBaK6detKks6fP29VlwAAAAAAACgElu1BNHjwYO3YsUNLly7Vww8/bFW3KAKqvbnW2SHAhZya0sXZIQAAAAAAHGTZDKJnn31WYWFh+vLLL7Vo0SKrugUAAAAAAEABs2wGUUxMjD755BMNGzZMTz31lFauXKn+/furbt268vHxyfV69i4CAAAAAABwDssKRNWqVZPNZpMkGYah5cuXa/ny5Xm61mazKSUlxapQAAAAAAAA4ADLCkTSzcJQVscAAAAAAABwXZYViCIiIqzqCgAAAAAAAIXIsgLRoEGDrOoKAAAAAAAAhciyp5gBAAAAAACgaKJABAAAAAAAUMxZukl1urS0NG3ZskXbt2/X+fPnlZiYqHfeeUeVKlUy2yQnJyslJUXu7u7y8vIqiDAAAAAAAACQB5YXiNauXasXX3xRp06dyvD5qFGjMhSIZs+erRdeeEG+vr46d+6cSpUqZXUoAAC4hGpvrnV2CHAhp6Z0cXYIAAAAmVi6xGzWrFnq1q2bTp48KcMwFBgYmO3j7ocMGaKAgABduXJFK1eutDIMAAAAAAAAOMCyAtGxY8c0cuRISVJ4eLh++eUXxcbGZtve09NTvXr1kmEY2rhx422NfebMGb322muqV6+eSpUqpbJly6pFixb68MMPlZiYeFt9T5w4UTabLU+vLVu23NZYAAAAAAAAzmBZgeijjz7SjRs31KBBA61bt05169bN9Zq2bdtKkvbt25fvcdeuXavGjRtr2rRpOnz4sBITE3Xp0iXt2rVLr7/+upo3b64TJ07ku38AAAAAAIA7nWV7EG3evFk2m00vv/yyPD0983RNjRo1JN2cAZQf+/fvV58+fZSYmChfX1+NGTNGYWFhSkpK0uLFi/XFF1/oyJEj6tKli3bt2iVfX998jZPuwIEDOZ6/9957b6t/AAAAAAAAZ7CsQBQTEyNJatq0aZ6vSd+YOr/LwF5++WUlJibKw8NDGzdu1P3332+eCw8PV61atTR69GgdPnxY06dP1/jx4/M1TrqGDRve1vUAAAAAAACuyLIlZjabTZKy3ZQ6KxcuXJAk+fn5OTzerl27zD1/hgwZkqE4lG7UqFGqV6+epP+/BA4AAAAAAAAZWVYgCgoKkiT9+uuveb4mKipKklStWjWHx/vmm2/M46effjrLNm5ubho4cKAk6dKlS2wiDQAAAAAAkAXLCkTt2rWTYRhauHBhntrHxcVp5syZstlsCg8Pd3i8H374QdLNZWrBwcHZtgsNDTWPf/zxR4fHAQAAAAAAuNNZViAaNmyYJGndunWKiIjIse1vv/2mzp07Ky4uTu7u7ua1jjh06JAkqWbNmvLwyH4rJfunqaVfk18dOnRQYGCgPD09VaFCBbVv315TpkzRpUuXbqtfAAAAAAAAZ7KsQBQSEqIRI0bIMAwNHTpUvXv31tdff22ej46O1pIlSzRkyBDVqVNHe/bskc1m06hRo1SzZk2Hxrp27Zri4uIkSZUrV86xbZkyZczNsNM30s6vTZs26eLFi7px44YuXLigqKgojRkzRtWrV9eqVatuq28AAAAAAABnsewpZpL0ySef6OrVq5o/f75WrFihFStWmJtXP/nkk2a79I2sBw8erHfffdfhcRISEszjvDy6vlSpUrp69aquXLni8FiS1KhRI3Xv3l0tWrRQUFCQbty4oSNHjmjBggXauHGj/vrrL/Xq1UvffvutHnnkkRz7un79uq5fv26+j4+Pz1dMAAAAAAAAVrFsBpEkubu7a968eVq6dKmaNWsmwzCyfNWvX18LFy7UnDlzzAKSI65du2Yee3p65trey8tLkpSUlOTwWC+//LKio6M1adIkPfroo2revLlatmypgQMHasOGDZoxY4YkKTU1VUOHDs11jPfee0/+/v7mq0qVKg7HBAAAAAAAYCVLZxCl69Wrl3r16qVz585p9+7dio2NVWpqqgIDA9WsWTPVqFHjtvr39vY2j5OTk3Ntnz5jp2TJkg6PFRAQkOP54cOHa/fu3Zo1a5bOnTunFStWZJgtdasxY8bo1VdfNd/Hx8dTJAIAAAAAAE5VIAWidEFBQerWrZvl/ZYuXdo8zsuysatXr0rK23K0/Bg+fLhmzZolSYqKisqxQOTl5WXOaAIAAAAAAHAFli4xKyze3t4qV66cpJtPRMvJpUuXzAJRQc3UqV+/vnl89uzZAhkDAAAAAACgoBTJApEk1atXT5J07NgxpaSkZNvu8OHDma6xWvqm2wAAAAAAAEWRZUvMJk2adFvXjx8/3qH2DzzwgH744QddvXpVe/bsUcuWLbNsFxUVZR63adPmtmLMzi+//GIeBwUFFcgYAAAAAAAABcWyAtHEiRPz9USydI4WiLp376733ntPkhQREZFlgSgtLU1ffvmlpJubTYeFheU7vpzMnDnTPA4NDS2QMQAAAAAAAAqKpUvMsnusfVavW9s7qkWLFmrbtq0kafbs2dq+fXumNtOmTdOhQ4ckSS+99JJKlCiR4fzcuXNls9lks9k0ceLETNcfOHBAx44dyzGOmTNnavbs2ZKku+66Sz169HD4XgAAAAAAAJzJshlEaWlpubZJTEzUkSNHtGDBAn3yyScKCQnR8uXLVbFixXyN+fHHH6tNmzZKSkpSx44dNXbsWIWFhSkpKUmLFy/W559/LkmqXbu2Ro0a5XD/e/bs0dChQxUWFqZHHnlEjRo1UmBgoFJSUnT48GF99dVX+u677yRJ7u7umjlzpkqVKpWvewEAAAAAAHCWAn3M/a18fHzUrFkzNWvWTN26dVOnTp3UqVMn7dixQ97e3g7316xZMy1ZskRPPfWU4uPjNXbs2ExtateurbVr16p06dL5ijk1NVWbNm3Spk2bsm0TGBio2bNnq1u3bvkaAwAAAAAAwJmc9hSzdu3aacSIETpw4IA+/vjjfPfTtWtXRUdH65VXXlHt2rXl4+OjgIAA3XfffXr//fe1d+9e1axZM199d+7cWbNnz9bQoUMVHBysypUrq2TJkvL29lZQUJAeeeQRffzxxzpx4oQee+yxfN8DAAAAAACAM9kMJz6j/fvvv9dDDz2kJk2aaO/evc4Kw6ni4+Pl7++vy5cvy8/Pz9nh5Eu1N9c6OwS4kFNTujg7BMDl8DsJe/xOApnxOwl7/E4C1nGk5uC0GUSSVLZsWUnS8ePHnRkGAAAAAABAsebUAtGRI0ecOTwAAAAAAADkxALRX3/9pX/84x+y2WyqX7++s8IAAAAAAAAo9ix7itnWrVtzbZOWlqZLly5p9+7dioiI0B9//CFJGjx4sFVhAAAAAAAAwEGWFYjat28vm82W5/bpe2P36NFDw4cPtyoMAAAAAAAAOMjSJWaGYeT51bhxY82YMUPLli1zqLAEAAAAAAAAa1k2gygyMjLXNm5ubipdurTuvfde+fv7WzU0AAAAAAAAboNlBaLQ0FCrugIAAAAAAEAhcupj7gEAAAAAAOB8FIgAAAAAAACKOQpEAAAAAAAAxZzDexCFh4dbHoTNZtPmzZst7xcAAAAAAAC5c7hAtGXLFtlsNhmGcduDp/fDY+4BAAAAAACcx+ECUbt27SjoAAAAAAAA3EHyNYMIAAAAAAAAdw6HC0TR0dGSpLp168rT09PygAAAAAAAAFC4HC4QNW3aVG5uboqOjlb9+vXNzydNmiRJev7551WuXDnrIgQAAAAAAECBcrhAJCnLDaonTpwom82mxx9/nAIRAAAAAABAEeLm6AUlSpSQJCUlJVkeDAAAAAAAAAqfwwWiihUrSpL27NljeTAAAAAAAAAofPl6zP3ChQv1xhtv6Pjx46pdu7Y5q0iSVq1apd27dzscyMCBAx2+BgAAAAAAALfP4QLRmDFjtHLlSl2+fFkffvhhhnOGYejvf/+7w0HYbDYKRAAAAAAAAE7i8BKzBg0aaOvWrXrooYdUokQJGYaRYdPq9PeOvgAAAAAAAOAc+XqKWXBwsDZu3KiUlBTFxcXp2rVrql69umw2mzZs2KBatWpZHScAAAAAAAAKSL4KRObFHh666667MnwWFBSkqlWr3lZQAAAAAAAAKDy3VSCyN2HCBElShQoVrOoSAAAAAAAAhcDyAhEAAAAAAACKFoc3qQYAAAAAAMCdxbIZRPb+/PNPbd++XSdOnFBCQoJSU1NzvWb8+PEFEQoAAAAAAAByYWmBKDY2Vq+88oqWLVumlJQUh66lQAQAAAAAAOAclhWILl26pAceeEDHjx+XYRhWdQsAAAAAAIACZtkeRFOmTNGxY8dkGIY6duyo//u//9OFCxeUmpqqtLS0XF8AAAAAAABwDstmEK1atUo2m01dunTR6tWrreoWAAAAAAAABcyyGURnzpyRJI0cOdKqLgEAAAAAAFAILCsQ+fr6SpIqVqxoVZcAAAAAAAAoBJYViBo1aiRJOn36tFVdAgAAAAAAoBBYViAaPny4DMPQ/PnzreoSAAAAAAAAhcCyAlGfPn3Ur18/rVy5UlOmTLGqWwAAAAAAABQwy55itnXrVg0dOlSnT5/WW2+9pRUrVqh///6qW7eufHx8cr2+Xbt2VoUCAAAAAAAAB1hWIGrfvr1sNpv5fs+ePdqzZ0+errXZbEpJSbEqFAAAAAAAADjAsgKRJBmGYWV3AAAAAAAAKASWFYgiIyOt6goAAAAAAACFyLICUWhoqFVdAQAAAAAAoBBZ9hQzAAAAAAAAFE0UiAAAAAAAAIq5fC0xmzRpktVxaPz48Zb3CQAAAAAAgNzlq0A0ceLEDI+0twIFIgAAAAAAAOfI9ybVVj7S3upiEwAAAAAAAPIuXwUiHmkPAAAAAABw58hXgYhH2gMAAAAAANw5eIoZAAAAAABAMUeBCAAAAAAAoJijQAQAAAAAAFDMUSACAAAAAAAo5igQAQAAAAAAFHMUiAAAAAAAAIo5CkQAAAAAAADFHAUiAAAAAACAYu6OKBCdOXNGr732murVq6dSpUqpbNmyatGihT788EMlJiZaNs7ixYvVqVMnVapUSd7e3qpWrZoGDBigHTt2WDYGAAAAAABAYfNwdgC3a+3atXryySd1+fJl87PExETt2rVLu3bt0qxZs7Ru3TpVr14932Ncu3ZNvXv31po1azJ8fvr0aZ0+fVoLFy7UxIkTNW7cuHyPAQAAAAAA4CxFegbR/v371adPH12+fFm+vr6aPHmyfvrpJ23evFnPPvusJOnIkSPq0qWLrly5ku9xhgwZYhaHwsLC9M0332jnzp2aPXu2atSoobS0NI0fP16zZs2y5L4AAAAAAAAKU5GeQfTyyy8rMTFRHh4e2rhxo+6//37zXHh4uGrVqqXRo0fr8OHDmj59usaPH+/wGFFRUVq4cKEkqWvXrlq5cqXc3d0lSSEhIerWrZuCg4N15swZjR49Wo8//rgCAgIsuT8AAAAAAIDCUGRnEO3atUtbtmyRdHOGj31xKN2oUaNUr149SdJHH32kGzduODzO1KlTJUnu7u76z3/+YxaH0pUrV07vv/++JOnSpUuaPXu2w2MAAAAAAAA4U5EtEH3zzTfm8dNPP51lGzc3Nw0cOFDSzeJNekEpr65cuaLNmzdLkjp06KDKlStn2a5nz57y8/OTJK1YscKhMQAAAAAAAJytyBaIfvjhB0lSqVKlFBwcnG270NBQ8/jHH390aIydO3fq+vXrmfq5laenp1q1amVek5+ZSgAAAAAAAM5SZAtEhw4dkiTVrFlTHh7Zb6VUt27dTNc4Osat/eQ0TkpKio4ePerQOAAAAAAAAM5UJAtE165dU1xcnCRlu+wrXZkyZVSqVClJUkxMjEPj2LfPbZwqVapkeR0AAAAAAICrK5JPMUtISDCPfX19c21fqlQpXb161eFH3TsyTnoRSlKO41y/ft1ctiZJly9fliTFx8c7FJsrSbue6OwQ4EJcIZcbTtjg7BDgQg6+3cnZIfA7iQz4nYSr4XcSrobfSbgaV/idzK/0/z0ZhpFr2yJZILp27Zp57OnpmWt7Ly8vSVJSUlKBjZM+Rm7jvPfee3r77bczfW4/Awkoyvw/cnYEQEbkJFwNOQlXQ07C1ZCTcDV3Qk4mJCTI398/xzZFskDk7e1tHicnJ+faPn3GTsmSJQtsHPtZQTmNM2bMGL366qvm+7S0NF28eFGBgYGy2WwOxQfXER8frypVqigmJsZ8oh3gTOQkXA05CVdDTsLVkJNwNeTkncEwDCUkJCgoKCjXtkWyQFS6dGnzOC/Lxq5evSopb8vR8jtO+hi5jePl5ZVhtpEkBQQEOBQXXJefnx8/nnAp5CRcDTkJV0NOwtWQk3A15GTRl9vMoXRFcpNqb29vlStXTpL022+/5dj20qVLZvHG0WVc9htT5zaO/cbULBcDAAAAAABFSZEsEElSvXr1JEnHjh1TSkpKtu0OHz6c6Zq8ql+/fpb95DSOh4eHatas6dA4AAAAAAAAzlRkC0QPPPCApJtLu/bs2ZNtu6ioKPO4TZs2Do0REhJibk5t38+tkpOTtWPHjkzXoPjw8vLShAkTMi0fBJyFnISrISfhashJuBpyEq6GnCx+bEZennXmgnbu3KmWLVtKkoYPH64ZM2ZkapOWlqaGDRvq0KFDCggIUGxsrEqUKOHQOJ07d9b69evl4eGhkydPZlh2lm7x4sXq16+fJGnq1Kl6/fXX83FHAAAAAAAAzlFkZxC1aNFCbdu2lSTNnj1b27dvz9Rm2rRpOnTokCTppZdeylQcmjt3rmw2m2w2myZOnJjlOK+99pokKSUlRSNHjlRqamqG83FxcXrjjTck3dxseujQobd1XwAAAAAAAIWtyBaIJOnjjz9WyZIllZKSoo4dO+q9997Tjh07FBkZqeHDh2v06NGSpNq1a2vUqFH5GiM8PFxPPPGEJGn16tXq0KGDVq9erd27dysiIkKtWrXSmTNnJElTpkxRmTJlrLk5AAAAAACAQlIkH3OfrlmzZlqyZImeeuopxcfHa+zYsZna1K5dW2vXrs3wyHpHzZkzR/Hx8Vq3bp0iIyMVGRmZ4bybm5vGjRun4cOH53sMAAAAAAAAZynSM4gkqWvXroqOjtYrr7yi2rVry8fHRwEBAbrvvvv0/vvva+/evbf9VLGSJUtq7dq1WrBggTp06KAKFSrI09NTVapUUf/+/fXjjz9mu0QNAAAAAADA1RXZTarh2rZs2aKwsLAsz3l7e6tcuXJq0qSJunfvrqeeekre3t6FHCFulZaWpsOHD2vnzp3auXOndu3apejoaCUnJ0uSIiMj1b59e+cGeRvIyaLn2rVr2rBhgzZt2qSdO3fq6NGjSkhIUOnSpVWnTh116tRJw4cPV6VKlZwdar6Qk0XPoUOHtHnzZu3atUsHDhxQbGys4uLi5O7urooVKyokJET9+/dXt27dZLPZnB2uw8jJO0diYqIaNmyokydPSpKqVq2qU6dOOTeofCAni565c+fq6aefzlPbiIgIDR48uGADshg5WfTt3LlTc+fOVWRkpM6ePau0tDRVrFhRdevW1YMPPqgBAwaofPnyzg7TeQygAERGRhqS8vSqU6eOceTIEWeHXORMmDDB/A6tMHfu3Bz/nCIjIy0Zx1nIyYJnZU7u37/fKF26dK5/VqVLlzaWLFliQfSFj5wseFb/Tj755JN5+vMKDQ01/vzzT0vGLEzkZMGzOiezM2rUqAx/XlWrVi3Q8QoKOVnwrM7JiIiIPP+ZRUREWDJmYSInC15B/U5eu3bNGDp0qGGz2XL8c1u5cqWl4xY1RXoPIhQNzz33nJ5//nnzfWJiovbt26ePPvpIhw4d0pEjR/Twww/rf//7n0qWLOnESIs3w24yYYkSJdSwYUOlpKTowIEDToyqYJCTri8+Pl4JCQmSpDZt2ujRRx/Vfffdp8DAQF24cEErVqzQrFmzlJCQoP79+6t06dJ65JFHnBx1/pGTRYOHh4datmypNm3aqFGjRrrrrrtUvnx5Xbp0SYcPH9bMmTN18OBBRUVFqWvXrvrhhx/k5lY0V/OTk0XX3r179dFHH8nb21slSpQwf0uLOnKy6NmwYYOCgoKyPV+5cuVCjMZ65GTRkZycrB49emj9+vWSpLZt22rgwIGqV6+ePDw8dPr0ae3fv19Lly51cqQuwNkVKtyZ7KvrEyZMyLJNYmKi0aJFC7PdJ598UrhBFnFWV9d//vln4+OPPza2b99uJCUlZRrjTppBRE4WDCtzctu2bUafPn2M//3vf9m2+eabb8x/BapRo4aRlpZ22+MWJnKy4Fn9O3njxo0cz6ekpBg9e/Y0x1y9erUl4xYWcrLgFfQMopSUFCM4ONiQZEyaNMmoWrXqHTODiJwsGAU5g+jkyZOW9OlKyMmCVxC/k+PGjTP7/PDDD3Nsm5ycbNm4RVHR/Gct3BFKliypyZMnm+/TK7pwjhYtWujFF19Uq1atiu16aXLSdbRu3VpLlixR/fr1s23z2GOPqWfPnpKk48ePa9++fYUUXeEhJ12Lh0fOE6/d3d01evRo8/3WrVsLOqRCR066to8//lh79uxRnTp19MYbbzg7nEJBTsLVkJOu5cSJE5oyZYokafDgwRo1alSO7UuUKFEYYbksCkRwqlatWpnHp0+fNo9PnTolm80mm82muXPnSpJWrFihzp07KygoSB4eHllumPztt9/q8ccfV+XKleXl5aXAwEDdf//9mjJliq5cuZJtHHPnzjXHO3XqlJKTkzV9+nTdd9998vf3V9myZdW+fXutXbs2w3UJCQmaOnWqmjVrJj8/PwUEBKhDhw7avHlztmNt2bLFHGvLli1KS0vTF198odatW6ts2bIqVaqUmjRponfffVdJSUnZxvr222+bn6X3Z/8qiptRugJysmjlpP1GkcePH7e8f1dAThatnCxVqpR5fO3aNcv7dwXkpGvm5OnTpzV+/HhJ0meffSZPT89891XUkJOumZPFGTnpOjn5+eef68aNG7LZbOZvJHLg7ClMuDPlZfqlYRhGUlKS2a5u3brm5ydPnjQ/nzNnjjFgwIAsNwG176dHjx45bjgWFBRk7N27N8s47KfD7t+/32jZsmW2/UybNs0wDMM4ffq00aBBgyzb2Gw2Y/78+bl+Nxs2bDAefvjhbMeqV6+ece7cuWxjzellxbTe4rbEzDDISVfPyVtNmzbN7H/58uWW91+QyMk7MyfHjh1r9v/vf//b8v4LEjlZtHOyc+fOhiRjwIAB5mfFYYmZYZCTrpSTLDG7iZx0nZysXr26IckICQkxP0tNTTViYmKMEydOGImJiQ71d6ejQIQCkdcfz59//tlsFx4ebn5u/+PZuHFjQ5LRtm1bY+HChcbu3buNTZs2GbNmzTLb9+nTx2zfpEkT48svvzR27dplbNiwwXj66afNfUrKli1r/Pbbb5nisP9BatmypeHh4WE8//zzxnfffWfs3r3bmDVrllGpUiVDkuHm5mYcOHDACA4ONkqWLGm8+eabxpYtW4xdu3YZH330keHv729IN5+u9Mcff+T43YSEhBiSjI4dOxorV640du/ebaxcudLo0KGD2aZZs2YZ9r24dOmSceDAAeO5554z2xw4cCDTy4r1s8WxQEROunZO3qpbt27mmDntV+SKyMk7JycvXLhg/PTTT8Yzzzxjfo+BgYHGpUuXLOm/sJCTRTcnFy1aZEgyypQpkyH+4lIgIiddJyftv4PQ0FCjQoUKRokSJYzAwECjZcuWxltvvZXld1dUkJNFKydjY2PNvl588UXj8uXLxksvvWSUKVPG/NzDw8No166dsWbNmjz3eyejQIQCkdcfz8cee8xsN2nSJPNz+x9PScbAgQOz3YB2zZo1ZrsHH3zQuH79eqY2n3/+udmmT58+mc7b/3jabLYsH28YHR1tuLu7G5KM8uXLG15eXsaOHTsytVu7dq3Z1/Tp03P8biQZw4YNy/K+hgwZYrbJ6l+hC+NRucWxQEROunZO2tu3b595/w0aNCiUMa1EThbtnAwNDc0Qo/2rbNmyRlRUlOVjFjRysmjm5MWLF42KFSsakoyZM2dmOFdcCkTkpOvkZF5mgXh7exszZsywZLzCRk4WrZzcsmWL2dcbb7xh1KhRI8fcfOWVV257zKKOAhEKRE4/nomJicZPP/1kdO3a1Wzj5+dnxMbGmm3sfzwDAgKM+Pj4bMd65JFHDElGiRIljDNnzmTb7qGHHjKkm1XinKY09u3bN9s+7P+D4M0338y2XfpfyHr06JHpnP13U7FiRePq1atZ9pGQkGCUL1/ekGTUr18/03kKRI4hJ++MnEx37do147777jPHW7VqVYGPaTVysmjnZHYFor/97W9Z/stqUUBOFs2cTP+Prfvvvz/Tf2jeyQUictI1czIiIsKoXr268dprrxnLly83du7caezcudNYvHix0bt3b3PGi5S5oFkUkJNFKydXrFhh9uXl5WVIMlq3bm1ERUUZiYmJxsWLF40FCxaYs6gkGZ999tltj1uUsUk1Ctzbb7+dYWMxHx8ftW7dWt9++60kyc/PT8uXL1f58uWzvL5r164qXbp0ludSUlIUFRUlSerQoYOqVKmSbRzPPvusec2WLVuybffEE09ke65x48bmcd++fXNtd+LEiWzbSFKfPn3k4+OT5TlfX1/16dNHkvTLL7/o999/z7Ev5B05mb2ikpMvvPCCdu/eLUkaNGiQunXr5rRYrEBOZs9VczIiIkIHDhxQdHS0tm7dqunTp6tWrVr69NNPNWTIEP3xxx+FFktBICez50o5uXXrVs2ZM0ceHh6aMWOGbDZbgY7nTORk9lwpJ3v06KFjx47pgw8+UM+ePRUSEqKQkBD17dtXX3/9tVavXm0+JeqVV17R+fPnCzSegkROZs9VcvLq1avm8fXr1xUcHKzNmzerXbt2KlmypMqUKaP+/fsrKirKfMjE+PHjs9xEu7igQASnqVKliv72t7/pwIEDeuihh7JtZ/+DdasTJ04oMTFRktSyZcscx7M/f/DgwWzb1a5dO9tzAQEBDrVLSEjIMaaQkJAcz7do0cI8zilmWIOcLBo5+d5772nWrFmSpODgYH366adOiaMwkJOum5P33nuvGjZsqEaNGqlt27Z65ZVXFB0drc6dO2vNmjUKCQnRb7/9VmjxFBZy0nVy8vr16xo2bJgMw9BLL72U43d+JyMnXScnJcnf3z/HQuWjjz6qCRMmSJISExM1e/bsAo3HGchJ18lJb2/vDO8nT56c6TNJqlWrlp577jlJ0oULF7Rp06YCi8nVeTg7ANz5nnvuOT3//PPme29vbwUGBqpMmTJ5uj6ndhcvXjSPK1asmGM/d911V5bX3Sq7arckubm5OdQuNTU1x5gqVKiQ43n7e8opZjiGnMyeq+fkzJkzNXbsWElSnTp1tH79+gyPFS+qyMnsuXpO2vP29lZERISqVq2qmJgYjR49WgsXLnRqTPlFTmbPVXJy8uTJOnLkiKpUqaKJEycW2DiugpzMnqvkZF49++yzGjdunAzDUFRUlN566y1nh5Qv5GT2XCUn7WdoeXp6KiwsLNu2nTp10ocffihJ2rVrl7p27VpgcbkyCkQocBUqVFDDhg3zfb27u3ue2hXFadW5xWwYRiFFUryQk9lz5ZxctGiR+RexqlWratOmTdlO2y5qyMnsuXJOZqVcuXJq06aNvvvuO61atUopKSny8Ch6f90iJ7PnKjn5/vvvS5IeeughrVmzJss26csrrl69qsWLF0u6+WcbHh5eKDFaiZzMnqvkZF5VqFBB5cqV04ULF3T27Flnh5Nv5GT2XCUn7ZfmVaxYUZ6ennlqGxsbW6BxubKi9zcWwE7ZsmXN49zWMNuft7/OmXLbo8L+x8lVYkbOyMmCsXr1ag0cOFBpaWmqVKmSNm/erMqVKxfa+EUZOVn40guXiYmJunDhgipVquTkiFwLOWmN5ORkSTf3w4qIiMixbVxcnPr16ydJCg0NLZIFooJEThY+VytauRpy0hq1atVSiRIldOPGjVxnPdmfL4r/sGMV9iBCkVa9enVzGuTPP/+cY9udO3eax7dT7bfSrl278nz+1piL4r8mFAfkpPU2b96sPn36KCUlRYGBgfruu+9Uo0aNAhnrTkROFj77fxH39fV1SgyujJyEqyEnC1dsbKz+/PNPSVJQUFChj18UkJPWKFGihO6//35JN4tW9ptW3+r48ePm8d13321ZDEUNBSIUaR4eHgoNDZUkfffdd4qJicm2bfqmtu7u7mrfvn1hhJerpUuXZrtL/tWrV/X1119LkurXr5/pX6DtN1i7fv16wQUJh5CTN1mVkz/99JMee+wxXb9+XX5+ftqwYYMaNGhgSd/FBTl5U2H9Tp49e1bbt2+XdHMpZHZPqCnOyMmbbjcnDcPI9VW1alVJN3Mx/bOcnnJUXJGTNxXW7+Tnn39uziBK/96RETl5kxU52atXL0k3ZwitWrUq23YrVqwwj9u2bXvb4xZVFIhQ5I0cOVKSdOPGDT3zzDPmlGt7c+bM0caNGyXd/JFwlen+58+f16hRo7I89+qrr5rTL9N31bdnfw/2FW84HzlpTU7u27dPXbp00dWrV1WqVCmtW7dOwcHBt91vcURO3n5O/vrrr/r+++9zbHP58mX169fP/H4HDBhwW2PeychJ/r/b1ZCTt5+Tp06d0t69e3Nss2bNGv3jH/+QdLMQ8PTTT9/WmHcyctKa38lnnnnG3DR77NixWS5/27Jli+bPny/p5oymNm3a3Pa4RVXxXVyHO0aXLl3Uu3dvLV26VJs2bVLLli01atQo1atXT5cuXdLixYs1Z84cSTfXuE6fPt3JEf9/9913nz777DOdPHlSI0aMUJUqVRQTE6PPPvtMGzZskCQ1a9ZMI0aMyHRt69atzeNXXnlFb731lipVqmROy6xWrZrD62fnzp2b4f2+ffvM4//7v//TqVOnzPc1a9bUAw884FD/xQU5efs5efz4cXXq1El//fWXJOmdd96Rv79/jo9CrVChQq5PzSiuyMnbz8lz587pwQcfVJMmTdS9e3cFBwfrrrvukoeHh86fP69t27Zp9uzZ5l4QDRs21Jtvvnm7t3/HIiet+/9uWIOcvP2cPHXqlMLCwnT//fera9euatq0qSpUqCDDMHTixAktW7ZMy5YtM2cPffjhh8V6KU9uyElrfid9fX31r3/9S/369dPp06cVEhKiN998Uy1atNC1a9e0fv16/fOf/1Rqaqo8PDw0Y8aM4r0c2AAKQGRkpCHJkGRMmDDB4etPnjxpXh8REZFr+6SkJKNHjx7mNVm9goKCjL1792Z5fUREhNnu5MmT2Y4zYcIEs11OBg0aZEgyqlatmumc/XezYcMGo2PHjtnGXLduXePs2bPZjtOnT59sr83pPrKT0/d362vQoEEO9+9M5GTRykn7+8/rKz9/rs5EThatnLSPKbdXly5djNjY2Dz37SrIyaKVk3lRtWrVbO+pKCAni1ZO5vV30sfHx5g5c2ae+3Ul5GTRykl7//73vw1PT89s+/X19TW++eabfPV9J2GJGe4I3t7eWrFihVavXq2ePXsqKChInp6eKlOmjFq2bKn33ntPR44cUdOmTZ0dagaenp5av369/vOf/6hVq1YKCAiQj4+PGjVqpHfeeUf//e9/c9y876uvvtLUqVPVokUL+fv7y82N/0m7CnKSnHQ15OTt5WSbNm0UFRWlCRMm6MEHH1StWrXk5+cnDw8PlS1bVsHBwXr++ef1448/as2aNeaTzJA9cpLfSVdDTt5eTgYHB+urr77SyJEj1bJlS91zzz3y8fGRp6enKlasqPDwcE2ePFknT57UsGHD8nu7xQo5ad3v5MiRI/Xf//5Xzz33nGrWrKmSJUvK19dXjRs31ujRo/Xrr7/qscceu+1xijqbYfCMQaAwbdmyRWFhYZKkyMhIl9lMDsUXOQlXQ07C1ZCTcDXkJFwNOXln4J8sAAAAAAAAijkKRAAAAAAAAMUcBSIAAAAAAIBijgIRAAAAAABAMUeBCAAAAAAAoJjjKWYAAAAAAADFHDOIAAAAAAAAijkKRAAAAAAAAMUcBSIAAAAAAIBijgIRAAAAAABAMUeBCAAAAAAAoJijQAQAAAAAAFDMUSACAAAAAAAo5igQAQAAAAAAFHMUiAAAAAAAAIq5/wf9nDXpTH4LBgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# printing as prompt x and gen y\n", + "\n", + "all_sentences = []\n", + "for i in range(len(attr.prompt_sentences)):\n", + " all_sentences.append(\"Prompt \" + str(i + 1))\n", + "\n", + "generation_sentences = []\n", + "for i in range(len(attr.generation_sentences)):\n", + " all_sentences.append(\"Gen \" + str(i + 1))\n", + " generation_sentences.append(\"Gen \" + str(i + 1))\n", + "\n", + "\n", + "new_attr = llm_attr.LLMAttributionResult(tokenizer, attr.attribution_matrix, attr.prompt_tokens, attr.generation_tokens, attr.all_tokens)\n", + "new_attr.compute_sentence_attr(norm = False)\n", + "\n", + "new_attr.generation_sentences = generation_sentences\n", + "new_attr.all_sentences = all_sentences\n", + "new_attr.prompt_sentences = all_sentences[:len(new_attr.prompt_sentences)]\n", + "\n", + "new_attr.plot_attr_table_sentence()\n", + "\n", + "og = new_attr.sentence_attr.clone()\n", + "\n", + "thresh = 0.25\n", + "new_attr.draw_graph(cmap = plt.cm.Blues, wrap_width=18, thresh = thresh, spacing = 2, arrow_mod=0.3, rad = 0.3)\n", + "\n", + "plt.rcParams['font.size'] = 20\n", + "\n", + "new_attr.sentence_attr = attrs[1]\n", + "new_attr.plot_context_attr_sentence(\"Row Attribution\")\n", + "\n", + "new_attr.sentence_attr = attrs[2]\n", + "new_attr.plot_context_attr_sentence(\"CAGE Attribution\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/quickstart.py b/examples/quickstart.py new file mode 100644 index 0000000000000000000000000000000000000000..2eea798dd51659a309a35c4815fe0ff156b7e885 --- /dev/null +++ b/examples/quickstart.py @@ -0,0 +1,44 @@ +from __future__ import annotations + +import argparse + +from flashtrace import FlashTrace, load_model_and_tokenizer + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description="FlashTrace quickstart example.") + parser.add_argument("--model", required=True, help="Hugging Face model id or local model path.") + parser.add_argument("--prompt", required=True, help="Prompt text.") + parser.add_argument("--target", help="Target response text.") + parser.add_argument("--output-span", default=None, help="Inclusive generation-token span START:END.") + parser.add_argument("--reasoning-span", default=None, help="Inclusive generation-token span START:END.") + parser.add_argument("--html", default="trace.html", help="Output HTML path.") + parser.add_argument("--use-chat-template", action="store_true", help="Format prompts with the tokenizer chat template.") + return parser + + +def parse_span(value: str | None) -> tuple[int, int] | None: + from flashtrace.cli import parse_span as parse_cli_span + + return parse_cli_span(value) + + +def main() -> int: + args = build_parser().parse_args() + model, tokenizer = load_model_and_tokenizer(args.model) + tracer = FlashTrace(model, tokenizer, use_chat_template=args.use_chat_template) + trace = tracer.trace( + prompt=args.prompt, + target=args.target, + output_span=parse_span(args.output_span), + reasoning_span=parse_span(args.reasoning_span), + ) + for item in trace.topk_inputs(10): + print(f"{item.index}\t{item.score:.6f}\t{item.token!r}") + trace.to_html(args.html) + print(f"wrote {args.html}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/exp/case_study/README.md b/exp/case_study/README.md new file mode 100644 index 0000000000000000000000000000000000000000..2ca10a6514c4fa74e7c1ceae360018a23598eb45 --- /dev/null +++ b/exp/case_study/README.md @@ -0,0 +1,152 @@ +# FT ๅคš่ทณๆกˆไพ‹ๅˆ†ๆž & IFR ๆ ‡ๅ‡†ๅฏ่ง†ๅŒ–๏ผˆexp/case_study๏ผ‰ + +ๆญค็›ฎๅฝ•ๆไพ›ไธ€ไธช่ฝป้‡็š„ๅ•ๆ ทๆœฌ IFR ๅฏ่ง†ๅŒ–ๆต็จ‹๏ผŒไธๆ”นๅŠจๆ ธๅฟƒ่ฏ„ๆต‹ไปฃ็ ใ€‚ + +## ๅŠŸ่ƒฝ +- ่ฏปๅ–ๅ•ไธชๆ ทๆœฌ๏ผˆ้ป˜่ฎค `exp/exp2/data/morehopqa.jsonl`๏ผŒ็ดขๅผ• 0๏ผ‰ใ€‚ +- ๆ”ฏๆŒๅคš็งๆจกๅผ๏ผš + - `ft`๏ผšๅฝ“ๅ‰ไฝฟ็”จ็š„ๅคš่ทณ FT ๅฝ’ๅ› ๏ผˆๅ†…้ƒจ่ฐƒ็”จ `LLMIFRAttribution.calculate_ifr_multi_hop`๏ผ‰ใ€‚ + - `ifr`๏ผšๆ ‡ๅ‡† IFR๏ผˆๅ• hop๏ผ‰๏ผŒ้ป˜่ฎคๅฏนๆŒ‡ๅฎš sink span ๅš**่šๅˆ IFR**๏ผˆๅชๆ˜พ็คบ 1 ไธช้ขๆฟ๏ผ‰ใ€‚ + - `ifr_all_positions_output_only`๏ผšๅชๅฏน `sink_span` ่Œƒๅ›ดๅ†…็š„ output tokens ่ฎก็ฎ— IFR token-level ็Ÿฉ้˜ต๏ผŒๅนถๅŸบไบŽ่ฏฅ็Ÿฉ้˜ตๅพ—ๅˆฐ Row / Recursive๏ผˆCAGE๏ผ‰ไธคๅผ ้ขๆฟใ€‚ + - `attnlrp`๏ผšAttnLRP hop0๏ผˆๅค็”จ FT-AttnLRP ็š„ span-aggregate ้€ป่พ‘๏ผŒ็ญ‰ไปทไบŽ `LLMLRPAttribution.calculate_attnlrp_multi_hop(n_hops=0)`๏ผŒๅนถๅฏ่ง†ๅŒ– `raw_attributions[0].token_importance_total`๏ผ‰ใ€‚ + - `ft_attnlrp`๏ผšFT-AttnLRP๏ผˆไธฅๆ ผๅค็”จ `LLMLRPAttribution.calculate_attnlrp_aggregated_multi_hop`๏ผŒไธŽ `exp/exp2/` ไฟๆŒไธ€่‡ด๏ผ›็›ดๆŽฅๅฏ่ง†ๅŒ–ๆฏ hop ็š„ `token_importance_total`๏ผ‰ใ€‚ +- ๅฏ่ง†ๅŒ–ไธคไธช่ง†ๅ›พ๏ผš + - **่ฃๅ‰ชๅ‰ token ็บง๏ผˆfull๏ผ‰**๏ผšๅธฆ chat template ็š„ๅฎŒๆ•ดๅบๅˆ—็ƒญๅŠ›ๅ›พ๏ผˆtemplate + user prompt + generation๏ผ‰ใ€‚ + - **Prompt-only token ็บง**๏ผšๅชๆ˜พ็คบ user prompt tokens ็š„็ƒญๅŠ›ๅ›พ๏ผˆไธๅŒ…ๅซ generation tokens๏ผ‰ใ€‚ +- ็ƒญๅŠ›ๅ›พๆŒ‰ `|score|` ไธŠ่‰ฒ๏ผˆไธๅŒบๅˆ†ๆญฃ่ดŸ๏ผ‰๏ผ›ๆฏไธช้ขๆฟ็š„ full/prompt ไธคๅผ ๅ›พๅ„่‡ช็”จ p99.5(`|score|`) ็‹ฌ็ซ‹ๅฝ’ไธ€ๅŒ–้ขœ่‰ฒๆทฑๅบฆใ€‚ +- ่พ“ๅ‡บ JSON๏ผˆๅฎŒๆ•ดๆ•ฐๅ€ผ๏ผ‰ๅ’Œ HTML๏ผˆ้€่ทณ็ƒญๅŠ›ๅ›พ๏ผ‰ใ€‚ +- ้ขๅค–ๆไพ› MAS๏ผˆfaithfulness / token perturbation๏ผ‰ๅฏ่ง†ๅŒ–๏ผšๅฏนๆŒ‡ๅฎšๅฝ’ๅ› ๆ–นๆณ•ๅš token ็บงๆ‰ฐๅŠจ่ฏ„ไผฐ๏ผŒๅนถๆธฒๆŸ“ๆ‰ฐๅŠจๅฝฑๅ“็ƒญๅŠ›ๅ›พ + MAS ๅˆ†ๆ•ฐใ€‚ + +## ๅฟซ้€Ÿๅผ€ๅง‹ +```bash +# ๆ นๆฎๆœฌๅœฐๆจกๅž‹ไฟฎๆ”น model/model_path +# ๅคš่ทณ FT๏ผˆ้ป˜่ฎค๏ผ‰ ft_split_hop,ft_improve +python exp/case_study/run_ifr_case.py \ + --mode ft_split_hop \ + --dataset exp/exp2/data/morehopqa.jsonl \ + --index 0 \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 0 \ + --n_hops 3 + +# ๆ ‡ๅ‡† IFR๏ผˆๅ• hop๏ผŒๅฏๆŒ‡ๅฎš sink span๏ผ‰ +python exp/case_study/run_ifr_case.py \ + --mode ifr \ + --dataset exp/exp2/data/morehopqa.jsonl \ + --index 0 \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 0 \ + --sink_span 0 0 + +# IFR output-only๏ผšๅชๅœจ output ่Œƒๅ›ด่ฎก็ฎ— IFR ็Ÿฉ้˜ต๏ผŒๅนถ็”Ÿๆˆ Row/Recursive๏ผˆCAGE๏ผ‰ไธค้ขๆฟ +python exp/case_study/run_ifr_case.py \ + --mode ifr_all_positions_output_only \ + --dataset exp/exp2/data/short-morehopqa.jsonl \ + --index 0 \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 0 + +# AttnLRP hop0๏ผˆๅค็”จ FT-AttnLRP span-aggregate๏ผ›ๅฏ่ง†ๅŒ– hop0 raw ๅ‘้‡๏ผ‰ +python exp/case_study/run_ifr_case.py \ + --mode attnlrp \ + --dataset exp/exp2/data/morehopqa.jsonl \ + --index 0 \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 0 \ + --sink_span 0 20 + +# FT-attnLRP๏ผˆๅคš่ทณ้€’ๅฝ’ AttnLRP๏ผ‰ +python exp/case_study/run_ifr_case.py \ + --mode ft_attnlrp \ + --dataset exp/exp2/data/morehopqa.jsonl \ + --index 0 \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 0,2,3,4,5,7 \ + --n_hops 3 \ + --attnlrp_neg_handling abs \ + --attnlrp_norm_mode norm +``` + +ไบง็‰ฉไฝไบŽ `exp/case_study/out/`๏ผŒๆ–‡ไปถๅๅ‰็ผ€ๆ นๆฎๆจกๅผๅ˜ๅŒ–๏ผŒไพ‹ๅฆ‚๏ผš +- `ft_case__idx.json/html` +- `ifr_case__idx.json/html` +- `ifr_output_only_case__idx.json/html` +- `attnlrp_case__idx.json/html` +- `ft_attnlrp_case__idx.json/html` + +## MAS๏ผˆFaithfulness / Token Perturbation๏ผ‰ๅฏ่ง†ๅŒ– + +> ่ฏดๆ˜Ž๏ผš่ฟ™้‡Œ็š„ MAS ไธŽ้กน็›ฎ `llm_attr_eval.LLMAttributionEvaluator.faithfulness_test()` ไฟๆŒไธ€่‡ด๏ผš +> 1) ๅ…ˆๅฏนๆ ทๆœฌ่ท‘ๆŒ‡ๅฎšๆ–นๆณ•็š„ๅฝ’ๅ› ๏ผŒๅนถๅ– token-level attribution๏ผˆSeq / Row / Recursive๏ผ‰ใ€‚ +> 2) ๆŒ‰ prompt token ็š„้‡่ฆๆ€งๆŽ’ๅบ๏ผŒ้€ๆญฅๅฐ† token id ๆ›ฟๆขไธบ `tokenizer.pad_token_id`๏ผˆtoken ็บงๆ‰ฐๅŠจ๏ผ‰ใ€‚ +> 3) ็”จ `sum log p(generation + EOS | prompt)` ๅพ—ๅˆฐๅˆ†ๆ•ฐๆ›ฒ็บฟ๏ผŒ่ฎก็ฎ— RISE / MAS / RISE+APใ€‚ +> 4) ๅฏ่ง†ๅŒ–ๆ—ถ็”จโ€œๆฏไธ€ๆญฅๆ‰ฐๅŠจๅธฆๆฅ็š„่พน้™… logprob ๅ˜ๅŒ–โ€ไฝœไธบ token ๅˆ†ๆ•ฐ๏ผŒๆธฒๆŸ“ไธบ token spans ็š„โ€œๆ‰ฐๅŠจๅฝฑๅ“็ƒญๅŠ›ๅ›พโ€ใ€‚ + +```bash +# FT-IFR๏ผˆifr_multi_hop๏ผ›้ป˜่ฎค --method ft๏ผ‰ +python exp/case_study/run_mas_case.py \ + --dataset exp/exp2/data/short-morehopqa.jsonl \ + --index 0 \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 0 \ + --method ft \ + --n_hops 3 +``` + +ๅธธ็”จๆ–นๆณ•้€‰ๆ‹ฉ๏ผˆไธŽ `run_ifr_case.py` ็š„ๆจกๅผๅๅฏน้ฝ๏ผ‰๏ผš +```bash +# IFR๏ผˆ้œ€่ฆ sink_span๏ผ›้ป˜่ฎคไผšไผ˜ๅ…ˆไฝฟ็”จๆ•ฐๆฎ้›†็ผ“ๅญ˜ๅญ—ๆฎต๏ผ‰ +python exp/case_study/run_mas_case.py --method ifr --sink_span 0 20 ... + +# IFR output-only๏ผˆไป…ๅฏน sink_span ๅ†…็š„ output token ่ฎก็ฎ— IFR token-level matrix๏ผ‰ +python exp/case_study/run_mas_case.py --method ifr_all_positions_output_only --sink_span 0 20 ... + +# FT-IFR๏ผˆifr_multi_hop๏ผ‰ +python exp/case_study/run_mas_case.py --method ft --n_hops 1 --sink_span 0 20 --thinking_span 0 20 ... + +# AttnLRP hop0๏ผˆๅค็”จ FT-AttnLRP hop0๏ผ›ไป็„ถ้œ€่ฆ indices_to_explain/sink_span ๆฅๅ– Seq/Row/Rec๏ผ‰ +python exp/case_study/run_mas_case.py --method attnlrp --sink_span 0 20 ... + +# FT-AttnLRP๏ผˆattnlrp_aggregated_multi_hop๏ผ‰ +python exp/case_study/run_mas_case.py --method ft_attnlrp --n_hops 1 --sink_span 0 20 --thinking_span 0 20 ... +``` + +ไบง็‰ฉไฝไบŽ `exp/case_study/out/`๏ผŒๆ–‡ไปถๅๅ‰็ผ€ไธบ๏ผš +- `mas_case___idx.json/html` + +HTML ้ป˜่ฎคๅŒ…ๅซ 3 ไธช attribution ่ง†่ง’้ขๆฟ๏ผˆSeq / Row / Recursive๏ผ‰๏ผŒๆฏไธช้ขๆฟ้‡Œๆœ‰ 2 ่กŒ token ็บง็ƒญๅŠ›ๅ›พ๏ผš +- **Method attribution๏ผˆtoken weights๏ผ‰**๏ผš่ฏฅๆ–นๆณ•็š„ token ๅฝ’ๅ› ๆƒ้‡๏ผˆ็”จไบŽๆŽ’ๅบ/ๅฏ†ๅบฆ๏ผ‰ใ€‚ +- **Attribution-guided MAS marginal๏ผˆpath deltas๏ผ‰**๏ผšๆŒ‰ๅฝ’ๅ› ๆŽ’ๅบ้€ๆญฅๆ›ฟๆข็š„่พน้™…ๅฝฑๅ“๏ผˆ่ฟ™ๅฐฑๆ˜ฏ่ฏ„ๆต‹ไธญๅฎž้™…ไฝฟ็”จ็š„ๆ‰ฐๅŠจ่ทฏๅพ„๏ผ‰ใ€‚ + +## ๅœจๆต่งˆๅ™จไธญๆŸฅ็œ‹ HTML +1) ๅ…ˆ่ฟ่กŒไธŠ้ข็š„ๅ‘ฝไปค็”Ÿๆˆ `.html`๏ผˆ็ปˆ็ซฏไผšๆ‰“ๅฐๅฝขๅฆ‚ `wrote exp/case_study/out/...html`๏ผ‰ใ€‚ + +2) ๅœจไป“ๅบ“ๆ น็›ฎๅฝ•ๅฏๅŠจไธ€ไธช้™ๆ€ๆ–‡ไปถๆœๅŠก๏ผˆไปป้€‰ไธ€ไธช็ซฏๅฃ๏ผŒไพ‹ๅฆ‚ 8888๏ผ‰๏ผš +```bash +python -m http.server 8888 --directory exp/case_study/out +``` + +3) ็”จๆต่งˆๅ™จๆ‰“ๅผ€๏ผˆๆณจๆ„ๆ˜ฏ `http://`๏ผŒไธๆ˜ฏ `https://`๏ผ‰๏ผš +- ๆœฌๆœบ๏ผš`http://127.0.0.1:8888/<ไฝ ็š„htmlๆ–‡ไปถๅ>` +- ่ฟœ็จ‹ๆœบๅ™จ๏ผˆๆŽจ่็ซฏๅฃ่ฝฌๅ‘๏ผ‰๏ผšๅœจๆœฌๅœฐๆ‰ง่กŒ `ssh -L 8888:127.0.0.1:8888 @`๏ผŒ็„ถๅŽๅœจๆœฌๅœฐๆต่งˆๅ™จๆ‰“ๅผ€ `http://127.0.0.1:8888/<ไฝ ็š„htmlๆ–‡ไปถๅ>` + +ๅฆ‚ๆžœไฝ ๅœจ `http.server` ๆ—ฅๅฟ—้‡Œ็œ‹ๅˆฐๅคง้‡ `400 Bad request version` ไธ”ไผด้šไนฑ็ ๏ผŒ้€šๅธธๆ˜ฏๆœ‰ๅฎขๆˆท็ซฏ็”จ HTTPS ๅŽป่ฟžไบ† HTTP ็ซฏๅฃ๏ผ›่ฏท็กฎ่ฎคๆต่งˆๅ™จๅœฐๅ€ๆ ๆ˜ฏ `http://...`ใ€‚ + +## ๅฏ้€‰ๅ‚ๆ•ฐ +- `--sink_span a b` / `--thinking_span a b`๏ผš่ฆ†็›–็”Ÿๆˆไพง็š„ sink/thinking ๅฅๅญ span๏ผˆ้ป˜่ฎคไฝฟ็”จ็ผ“ๅญ˜ๅญ—ๆฎต๏ผ‰ใ€‚ +- `--attnlrp_neg_handling drop|abs`๏ผšFT-AttnLRP ๆฏ่ทณ่ดŸๅ€ผๅค„็†๏ผˆdrop=clamp>=0๏ผŒabs=ๅ–็ปๅฏนๅ€ผ๏ผ‰ใ€‚ +- `--attnlrp_norm_mode norm|no_norm`๏ผšFT-AttnLRP ๆญฃๅˆ™ๅŒ–ไธŽ hop ratio ๅผ€ๅ…ณ๏ผˆnorm=ๅ…จๅฑ€+thinking ๅฝ’ไธ€ๅŒ–ๅนถๅฏ็”จ ratio๏ผ›no_norm=ไธ‰่€…้ƒฝ็ฆ็”จ๏ผ‰ใ€‚ +- `--chunk_tokens` / `--sink_chunk_tokens`๏ผšIFR ๅˆ†ๅ—ๅ‚ๆ•ฐใ€‚ +- `--output_dir`๏ผšไฟฎๆ”น่พ“ๅ‡บ็›ฎๅฝ•ใ€‚ + +## ๆ–‡ไปถ่ฏดๆ˜Ž +- `run_ifr_case.py`๏ผšๅ‘ฝไปค่กŒๅ…ฅๅฃไธŽ่ฝ็›˜๏ผˆๆ”ฏๆŒ `ft`/`ifr`/`ifr_all_positions_output_only`/`attnlrp`/`ft_attnlrp` ๆจกๅผ๏ผ‰ใ€‚ +- `run_mas_case.py`๏ผšMAS๏ผˆfaithfulness / token perturbation๏ผ‰ๅฏ่ง†ๅŒ–ๅ…ฅๅฃไธŽ่ฝ็›˜๏ผˆๆ”ฏๆŒ `ifr`/`ifr_all_positions_output_only`/`ft`/`attnlrp`/`ft_attnlrp`๏ผ‰ใ€‚ +- `analysis.py`๏ผš้€่ทณๆธ…ๆด—ไธŽๅฐ่ฃ…๏ผˆtoken-level๏ผ‰ใ€‚ +- `viz.py`๏ผšHTML ๆธฒๆŸ“ไธŽ็ƒญๅŠ›ๅ›พใ€‚ diff --git a/exp/case_study/analysis.py b/exp/case_study/analysis.py new file mode 100644 index 0000000000000000000000000000000000000000..74287af9ecf30c48b9b5dd903191563028332d95 --- /dev/null +++ b/exp/case_study/analysis.py @@ -0,0 +1,74 @@ +"""Helpers for IFR case studies (hop-wise aggregation + sanitization). + +All utilities stay local to exp/case_study to avoid touching core eval code. +""" + +from __future__ import annotations + +from typing import Any, Dict, Iterable, List, Optional, Sequence + +import torch + + +def vector_stats(vec: torch.Tensor) -> Dict[str, float]: + if vec.numel() == 0: + return {"min": 0.0, "max": 0.0, "abs_max": 0.0, "mean": 0.0, "sum": 0.0} + v = vec.detach().to(dtype=torch.float32) + return { + "min": float(v.min().item()), + "max": float(v.max().item()), + "abs_max": float(v.abs().max().item()), + "mean": float(v.mean().item()), + "sum": float(v.sum().item()), + } + + +def tensor_to_list(x: Any) -> Any: + if torch.is_tensor(x): + return x.detach().cpu().tolist() + if isinstance(x, list): + return [tensor_to_list(v) for v in x] + if isinstance(x, dict): + return {k: tensor_to_list(v) for k, v in x.items()} + return x + + +def sanitize_ifr_meta(meta: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]: + """Drop bulky raw objects and convert tensors to Python lists for JSON.""" + + if meta is None: + return None + + cleaned: Dict[str, Any] = {} + for key, value in meta.items(): + if key == "raw": + continue + cleaned[key] = tensor_to_list(value) + return cleaned + + +def package_token_hops( + hop_vectors: Iterable[Sequence[float]], +) -> List[Dict[str, Any]]: + """Package per-hop token vectors without sentence aggregation. + + hop_vectors are assumed to already match the experiment's configured + postprocessing (e.g., FT-AttnLRP neg_handling/norm_mode). + """ + + packaged: List[Dict[str, Any]] = [] + for hop_idx, vec in enumerate(hop_vectors): + vec_tensor = torch.nan_to_num(torch.as_tensor(vec, dtype=torch.float32), nan=0.0) + token_scores = vec_tensor.tolist() + token_max = float(vec_tensor.abs().max().item()) if vec_tensor.numel() > 0 else 0.0 + total = float(vec_tensor.sum().item()) + packaged.append( + { + "hop": hop_idx, + "token_scores": token_scores, + "token_score_max": token_max, + "token_stats": vector_stats(vec_tensor), + "total_mass": total, + } + ) + return packaged diff --git a/exp/case_study/faithfulness_trace.py b/exp/case_study/faithfulness_trace.py new file mode 100644 index 0000000000000000000000000000000000000000..73a50eb426053562cb65b153246a1007b5b81df3 --- /dev/null +++ b/exp/case_study/faithfulness_trace.py @@ -0,0 +1,183 @@ +"""Faithfulness (MAS/RISE) trace utilities for exp/case_study. + +This module is intentionally aligned with `llm_attr_eval.LLMAttributionEvaluator.faithfulness_test`, +but additionally returns the full trace arrays needed for visualization and supports providing +`user_prompt_indices` to avoid fragile subsequence matching. +""" + +from __future__ import annotations + +from typing import Any, Dict, Optional, Sequence, List + +import numpy as np +import torch + +import llm_attr_eval + + +def _auc(arr: np.ndarray) -> float: + return float((arr.sum() - arr[0] / 2 - arr[-1] / 2) / max(1, (arr.shape[0] - 1))) + + +@torch.inference_mode() +def mas_trace( + llm_evaluator: llm_attr_eval.LLMAttributionEvaluator, + *, + attribution: torch.Tensor, + prompt: str, + generation: str, + user_prompt_indices: Optional[Sequence[int]] = None, + k: int = 20, +) -> Dict[str, Any]: + """Return a token-level faithfulness trace (RISE/MAS/RISE+AP) plus per-token deltas. + + attribution: [R, P] token attribution on prompt-side tokens only. + prompt: raw prompt string. + generation: target generation string; scored as generation + eos (if defined). + user_prompt_indices: optional absolute positions of each prompt token inside formatted prompt ids. + k: number of perturbation steps; each step perturbs ~1/k of prompt tokens. + """ + + if attribution.ndim != 2: + raise ValueError("Expected 2D prompt-side attribution matrix [R, P].") + + pad_token_id = llm_evaluator._ensure_pad_token_id() + + user_prompt = " " + prompt + formatted_prompt = llm_evaluator.format_prompt(user_prompt) + formatted_ids = llm_evaluator.tokenizer(formatted_prompt, return_tensors="pt", add_special_tokens=False).input_ids + + prompt_ids = formatted_ids.to(llm_evaluator.device) + prompt_ids_perturbed = prompt_ids.clone() + + eos = llm_evaluator.tokenizer.eos_token or "" + generation_ids = llm_evaluator.tokenizer( + generation + eos, + return_tensors="pt", + add_special_tokens=False, + ).input_ids.to(llm_evaluator.device) + + attr_cpu = attribution.detach().cpu() + w = attr_cpu.sum(0) + sorted_attr_indices = torch.argsort(w, descending=True) + attr_sum = float(w.sum().item()) + + P = int(w.numel()) + + prompt_positions: List[int] + if user_prompt_indices is not None: + prompt_positions = [int(x) for x in user_prompt_indices] + if len(prompt_positions) != P: + raise ValueError( + "user_prompt_indices length does not match prompt-side attribution length: " + f"indices P={len(prompt_positions)}, attr P={P}." + ) + if P and max(prompt_positions) >= int(prompt_ids_perturbed.shape[1]): + raise ValueError("user_prompt_indices contains an out-of-bounds index for formatted prompt ids.") + else: + user_ids = llm_evaluator.tokenizer(user_prompt, return_tensors="pt", add_special_tokens=False).input_ids + user_start = llm_evaluator._find_subsequence_start(formatted_ids[0], user_ids[0]) + if user_start is None: + raise RuntimeError("Failed to locate user prompt token span inside formatted chat prompt.") + if int(user_ids.shape[1]) != P: + raise ValueError( + "Prompt-side attribution length does not match tokenized user prompt length: " + f"attr P={P}, user_prompt P={int(user_ids.shape[1])}." + ) + prompt_positions = [int(user_start) + j for j in range(P)] + + if P > 0: + steps = int(k) if k is not None else 0 + if steps <= 0: + steps = 1 + steps = min(steps, P) + else: + steps = 0 + + scores = np.zeros(steps + 1, dtype=np.float64) + density = np.zeros(steps + 1, dtype=np.float64) + + scores[0] = ( + llm_evaluator.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + ) + density[0] = 1.0 + + if P == 0: + return { + "num_tokens": 0, + "sorted_attr_indices": [], + "scores_raw": scores.tolist(), + "density": density.tolist(), + "normalized_model_response": [1.0], + "alignment_penalty": [0.0], + "corrected_scores": [1.0], + "token_deltas_raw": [], + "attr_weights": [], + "metrics": {"RISE": 0.0, "MAS": 0.0, "RISE+AP": 0.0}, + } + + if attr_sum <= 0: + density = np.linspace(1.0, 0.0, steps + 1) + + per_token_delta = np.zeros(P, dtype=np.float64) + + base = P // steps + remainder = P % steps + start = 0 + for step in range(steps): + size = base + (1 if step < remainder else 0) + group = sorted_attr_indices[start : start + size] + start += size + + for idx_t in group: + idx = int(idx_t.item()) + abs_pos = int(prompt_positions[idx]) + prompt_ids_perturbed[0, abs_pos] = pad_token_id + scores[step + 1] = ( + llm_evaluator.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + ) + if attr_sum > 0: + dec = float(w.index_select(0, group).sum().item()) / attr_sum + density[step + 1] = density[step] - dec + + delta = scores[step] - scores[step + 1] + for idx_t in group: + idx = int(idx_t.item()) + per_token_delta[idx] = delta + + min_normalized_pred = 1.0 + normalized_model_response = scores.copy() + for i in range(len(scores)): + normalized_pred = (normalized_model_response[i] - scores[-1]) / (abs(scores[0] - scores[-1])) + normalized_pred = np.clip(normalized_pred, 0.0, 1.0) + min_normalized_pred = min(min_normalized_pred, normalized_pred) + normalized_model_response[i] = min_normalized_pred + + alignment_penalty = np.abs(normalized_model_response - density) + corrected_scores = normalized_model_response + alignment_penalty + corrected_scores = corrected_scores.clip(0.0, 1.0) + corrected_scores = (corrected_scores - np.min(corrected_scores)) / (np.max(corrected_scores) - np.min(corrected_scores)) + if np.isnan(corrected_scores).any(): + corrected_scores = np.linspace(1.0, 0.0, len(scores)) + + rise = _auc(normalized_model_response) + mas = _auc(corrected_scores) + rise_ap = _auc(normalized_model_response + alignment_penalty) + + if attr_sum > 0: + attr_weights = (w.numpy() / (attr_sum + 1e-12)).astype(np.float64) + else: + attr_weights = np.zeros(P, dtype=np.float64) + + return { + "num_tokens": P, + "sorted_attr_indices": [int(i.item()) for i in sorted_attr_indices], + "scores_raw": scores.tolist(), + "density": density.tolist(), + "normalized_model_response": normalized_model_response.tolist(), + "alignment_penalty": alignment_penalty.tolist(), + "corrected_scores": corrected_scores.tolist(), + "token_deltas_raw": per_token_delta.tolist(), + "attr_weights": attr_weights.tolist(), + "metrics": {"RISE": rise, "MAS": mas, "RISE+AP": rise_ap}, + } diff --git a/exp/case_study/run_ifr_case.py b/exp/case_study/run_ifr_case.py new file mode 100644 index 0000000000000000000000000000000000000000..92aa5db5f162d8fdf8682c5402625f7c8f44e696 --- /dev/null +++ b/exp/case_study/run_ifr_case.py @@ -0,0 +1,1225 @@ +#!/usr/bin/env python3 +"""Case study runner for FlashTrace and attribution baselines. + +Modes supported (all emit JSON + HTML under ``exp/case_study/out``): + +- ``ft``: FlashTrace (current project implementation; multi-hop IFR) +- ``ifr_in_all_gen``: Experimental multi-hop IFR variant (hops over CoT+output; scheme B, aligns with exp/exp2) +- ``ifr``: IFR span-aggregate visualization (single hop; one panel) +- ``ifr_all_positions``: IFR full matrix + CAGE (Row/Recursive panels) +- ``ifr_all_positions_output_only``: IFR output-only token matrix + CAGE (Row/Recursive panels) +- ``attnlrp``: AttnLRP hop0 (reuse FT-AttnLRP span-aggregate; visualize raw hop0 vector) +- ``ft_attnlrp``: FT-AttnLRP (multi-hop aggregated AttnLRP; matches exp/exp2) +""" + +from __future__ import annotations + +import argparse +import json +import os +import sys +import types +from pathlib import Path +from typing import Any, Dict, List, Optional, Sequence, Tuple + +# Avoid torchvision dependency when importing transformers (Longformer). +os.environ.setdefault("TRANSFORMERS_NO_TORCHVISION", "1") +os.environ.setdefault("DISABLE_TRANSFORMERS_IMAGE_TRANSFORMS", "1") + +def _early_set_cuda_visible_devices() -> None: + """Set CUDA_VISIBLE_DEVICES before importing torch/transformers. + + Note: CUDA device indices are re-mapped inside the process after applying the mask. + """ + + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("--cuda", type=str, default=None) + args, _ = parser.parse_known_args(sys.argv[1:]) + cuda = args.cuda.strip() if isinstance(args.cuda, str) else "" + if cuda and "," in cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = cuda + + +if __name__ == "__main__": + _early_set_cuda_visible_devices() + +import torch + +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + + +def _stub_torchvision() -> None: + """Provide minimal torchvision stubs so Longformer imports succeed without the real package.""" + + if "torchvision" in sys.modules: + return + + from importlib.machinery import ModuleSpec + + def _mk(name: str) -> types.ModuleType: + mod = types.ModuleType(name) + mod.__spec__ = ModuleSpec(name, loader=None) + return mod + + tv = _mk("torchvision") + tv.__dict__["__path__"] = [] + submods = ["transforms", "_meta_registrations", "datasets", "io", "models", "ops", "utils"] + for name in submods: + mod = _mk(f"torchvision.{name}") + sys.modules[f"torchvision.{name}"] = mod + setattr(tv, name, mod) + + class _InterpolationMode: + NEAREST = 0 + NEAREST_EXACT = 0 + BILINEAR = 1 + BICUBIC = 2 + LANCZOS = 3 + BOX = 4 + HAMMING = 5 + + sys.modules["torchvision.transforms"].InterpolationMode = _InterpolationMode + sys.modules["torchvision.transforms"].__all__ = ["InterpolationMode"] + + # ops + misc stub for timm/transformers imports + ops_mod = sys.modules.get("torchvision.ops") or _mk("torchvision.ops") + sys.modules["torchvision.ops"] = ops_mod + setattr(tv, "ops", ops_mod) + misc_mod = _mk("torchvision.ops.misc") + sys.modules["torchvision.ops.misc"] = misc_mod + setattr(ops_mod, "misc", misc_mod) + + class _FrozenBatchNorm2d: + def __init__(self, *args, **kwargs): + pass + + misc_mod.FrozenBatchNorm2d = _FrozenBatchNorm2d + + sys.modules["torchvision"] = tv + + +_stub_torchvision() + + +def _stub_timm() -> None: + """Provide minimal timm stubs to avoid optional vision deps.""" + + if "timm" in sys.modules: + return + + from importlib.machinery import ModuleSpec + + def _mk(name: str) -> types.ModuleType: + mod = types.ModuleType(name) + mod.__spec__ = ModuleSpec(name, loader=None) + return mod + + timm = _mk("timm") + timm.__dict__["__path__"] = [] + sys.modules["timm"] = timm + + data_mod = _mk("timm.data") + sys.modules["timm.data"] = data_mod + timm.data = data_mod + + class _ImageNetInfo: + pass + + def _infer_imagenet_subset(*args, **kwargs): + return None + + data_mod.ImageNetInfo = _ImageNetInfo + data_mod.infer_imagenet_subset = _infer_imagenet_subset + + layers_mod = _mk("timm.layers") + sys.modules["timm.layers"] = layers_mod + timm.layers = layers_mod + + create_norm_mod = _mk("timm.layers.create_norm") + sys.modules["timm.layers.create_norm"] = create_norm_mod + layers_mod.create_norm = create_norm_mod + + def _get_norm_layer(*args, **kwargs): + return None + + create_norm_mod.get_norm_layer = _get_norm_layer + + classifier_mod = _mk("timm.layers.classifier") + sys.modules["timm.layers.classifier"] = classifier_mod + layers_mod.classifier = classifier_mod + + +_stub_timm() + +import transformers + +# Provide light stubs if Longformer classes are unavailable; IFR case study does not use them. +if not hasattr(transformers, "LongformerTokenizer"): + class _DummyLongformerTokenizer: + def __init__(self, *args, **kwargs): + raise ImportError("LongformerTokenizer stubbed; install full transformers+torchvision if needed.") + transformers.LongformerTokenizer = _DummyLongformerTokenizer + +if not hasattr(transformers, "LongformerForMaskedLM"): + class _DummyLongformerForMaskedLM: + def __init__(self, *args, **kwargs): + raise ImportError("LongformerForMaskedLM stubbed; install full transformers+torchvision if needed.") + transformers.LongformerForMaskedLM = _DummyLongformerForMaskedLM + +if hasattr(transformers, "__all__"): + for _name in ["LongformerTokenizer", "LongformerForMaskedLM"]: + if _name not in transformers.__all__: + transformers.__all__.append(_name) + +# Gemma3n stubs (transformers may attempt to import even if unused) +if "transformers.models.gemma3n.configuration_gemma3n" not in sys.modules: + from importlib.machinery import ModuleSpec + + gemma_pkg = types.ModuleType("transformers.models.gemma3n") + gemma_pkg.__spec__ = ModuleSpec("transformers.models.gemma3n", loader=None, is_package=True) + sys.modules["transformers.models.gemma3n"] = gemma_pkg + + gemma_conf = types.ModuleType("transformers.models.gemma3n.configuration_gemma3n") + gemma_conf.__spec__ = ModuleSpec("transformers.models.gemma3n.configuration_gemma3n", loader=None) + + class Gemma3nConfig: + def __init__(self, *args, **kwargs): + self.model_type = "gemma3n" + + class Gemma3nTextConfig(Gemma3nConfig): + pass + + gemma_conf.Gemma3nConfig = Gemma3nConfig + gemma_conf.Gemma3nTextConfig = Gemma3nTextConfig + gemma_conf.__all__ = ["Gemma3nConfig", "Gemma3nTextConfig"] + sys.modules["transformers.models.gemma3n.configuration_gemma3n"] = gemma_conf + setattr(gemma_pkg, "configuration_gemma3n", gemma_conf) + + if hasattr(transformers, "__all__"): + for _nm in ["Gemma3nConfig", "Gemma3nTextConfig"]: + if _nm not in transformers.__all__: + transformers.__all__.append(_nm) + +import llm_attr +from exp.exp2 import dataset_utils as ds_utils +from evaluations.attribution_recovery import load_model + +from exp.case_study import analysis, viz + + +def resolve_device(cuda: Optional[str], cuda_num: int) -> str: + if cuda and isinstance(cuda, str) and "," in cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = cuda + return "auto" + if cuda and isinstance(cuda, str) and cuda.strip(): + try: + idx = int(cuda) + except Exception: + idx = 0 + return f"cuda:{idx}" if torch.cuda.is_available() else "cpu" + return f"cuda:{cuda_num}" if torch.cuda.is_available() else "cpu" + + +def load_example(dataset: str, index: int, data_root: Path) -> Tuple[ds_utils.CachedExample, str]: + """Load a single example from a cache path or dataset name.""" + + ds_path = Path(dataset) + if ds_path.exists(): + examples = ds_utils.read_cached_jsonl(ds_path) + dataset_name = ds_path.name + else: + loader = ds_utils.DatasetLoader(data_root=data_root) + examples = loader.load(dataset) + dataset_name = dataset + + if not examples: + raise ValueError(f"No examples found for dataset={dataset}") + + if index < 0: + index = len(examples) + index + if not (0 <= index < len(examples)): + raise IndexError(f"index {index} out of range for dataset with {len(examples)} examples") + + return examples[index], dataset_name + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser("IFR multi-hop case study") + parser.add_argument("--dataset", type=str, default="exp/exp2/data/morehopqa.jsonl", help="Dataset name or JSONL path.") + parser.add_argument("--data_root", type=str, default="exp/exp2/data", help="Cache root for dataset names.") + parser.add_argument("--index", type=int, default=0, help="Sample index (supports negative for reverse).") + parser.add_argument( + "--mode", + type=str, + choices=[ + "ft", + "ft_improve", + "ft_split_hop", + "ifr_in_all_gen", + "ifr", + "ifr_all_positions", + "ifr_all_positions_output_only", + "attnlrp", + "ft_attnlrp", + ], + default="ft", + help=( + "ft = FlashTrace (multi-hop IFR); ifr = standard IFR span-aggregate; " + "ifr_in_all_gen = multi-hop IFR over CoT+output (scheme B; exp2-aligned); " + "ifr_all_positions = full IFR matrix + CAGE row/rec; " + "ft_improve = FlashTrace (multi-hop IFR, stop-token soft deletion); " + "ft_split_hop = FlashTrace (split-hop IFR over segmented thinking span); " + "ifr_all_positions_output_only = output-only IFR matrix + CAGE row/rec; " + "attnlrp = AttnLRP hop0 (FT-AttnLRP span-aggregate); " + "ft_attnlrp = FT-AttnLRP (multi-hop aggregated; exp2)." + ), + ) + parser.add_argument("--model", type=str, default="qwen-8B", help="HF repo id (ignored if --model_path set).") + parser.add_argument("--model_path", type=str, default=None, help="Local model path to override --model.") + parser.add_argument("--cuda", type=str, default=None, help="CUDA spec (e.g., '0' or '0,1').") + parser.add_argument("--cuda_num", type=int, default=0, help="Fallback GPU index when --cuda unset.") + parser.add_argument("--n_hops", type=int, default=1, help="Number of hops for IFR multi-hop.") + parser.add_argument("--sink_span", type=int, nargs=2, default=None, help="Optional sink span over generation tokens.") + parser.add_argument("--thinking_span", type=int, nargs=2, default=None, help="Optional thinking span over generation tokens.") + parser.add_argument( + "--attnlrp_neg_handling", + type=str, + choices=["drop", "abs"], + default="drop", + help="FT-AttnLRP: how to handle negative values after each hop (drop=clamp>=0, abs=absolute value).", + ) + parser.add_argument( + "--attnlrp_norm_mode", + type=str, + choices=["norm", "no_norm"], + default="norm", + help="FT-AttnLRP: norm enables per-hop global+thinking normalization + ratios; no_norm disables all three.", + ) + parser.add_argument("--chunk_tokens", type=int, default=128, help="IFR chunk size.") + parser.add_argument("--sink_chunk_tokens", type=int, default=32, help="IFR sink chunk size.") + parser.add_argument("--output_dir", type=str, default="exp/case_study/out", help="Where to write HTML/JSON artifacts.") + return parser.parse_args() + + +def run_ft_multihop( + example: ds_utils.CachedExample, + model: Any, + tokenizer: Any, + *, + n_hops: int, + sink_span: Optional[Sequence[int]], + thinking_span: Optional[Sequence[int]], + chunk_tokens: int, + sink_chunk_tokens: int, +) -> Tuple[Any, Optional[Tuple[int, int]], Optional[Tuple[int, int]], Dict[str, Any]]: + """Execute FT (current multi-hop IFR) attribution for the selected example.""" + + attr = llm_attr.LLMIFRAttribution( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + + sink = tuple(sink_span) if sink_span is not None else tuple(example.sink_span) if example.sink_span else None + thinking = ( + tuple(thinking_span) + if thinking_span is not None + else tuple(example.thinking_span) if example.thinking_span else None + ) + + result = attr.calculate_ifr_multi_hop( + example.prompt, + target=example.target, + sink_span=sink, + thinking_span=thinking, + n_hops=n_hops, + ) + debug_info: Dict[str, Any] = { + "full_prompt_tokens": list(getattr(attr, "prompt_tokens", []) or []), + "generation_tokens": list(getattr(attr, "generation_tokens", []) or []), + "user_prompt_indices": list(getattr(attr, "user_prompt_indices", []) or []), + "chat_prompt_indices": list(getattr(attr, "chat_prompt_indices", []) or []), + "prompt_ids": getattr(attr, "prompt_ids", None).detach().cpu().tolist() if getattr(attr, "prompt_ids", None) is not None else None, + "generation_ids": getattr(attr, "generation_ids", None).detach().cpu().tolist() if getattr(attr, "generation_ids", None) is not None else None, + } + + raw_vectors = [] + if result.metadata and "ifr" in result.metadata: + raw_ifr = result.metadata["ifr"].get("raw") + if raw_ifr is not None and hasattr(raw_ifr, "raw_attributions"): + try: + raw_vectors = [r.token_importance_total.detach().cpu() for r in raw_ifr.raw_attributions] + except Exception: + raw_vectors = [] + debug_info["raw_hop_vectors"] = raw_vectors + + return result, sink, thinking, debug_info + + +def run_ft_multihop_improve( + example: ds_utils.CachedExample, + model: Any, + tokenizer: Any, + *, + n_hops: int, + sink_span: Optional[Sequence[int]], + thinking_span: Optional[Sequence[int]], + chunk_tokens: int, + sink_chunk_tokens: int, +) -> Tuple[Any, Optional[Tuple[int, int]], Optional[Tuple[int, int]], Dict[str, Any]]: + """Execute experimental FT (multi-hop IFR) with stop-token soft deletion.""" + + import ft_ifr_improve + + attr = ft_ifr_improve.LLMIFRAttributionImproved( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + + sink = tuple(sink_span) if sink_span is not None else tuple(example.sink_span) if example.sink_span else None + thinking = ( + tuple(thinking_span) + if thinking_span is not None + else tuple(example.thinking_span) if example.thinking_span else None + ) + + result = attr.calculate_ifr_multi_hop_stop_words( + example.prompt, + target=example.target, + sink_span=sink, + thinking_span=thinking, + n_hops=n_hops, + ) + + debug_info: Dict[str, Any] = { + "full_prompt_tokens": list(getattr(attr, "prompt_tokens", []) or []), + "generation_tokens": list(getattr(attr, "generation_tokens", []) or []), + "user_prompt_indices": list(getattr(attr, "user_prompt_indices", []) or []), + "chat_prompt_indices": list(getattr(attr, "chat_prompt_indices", []) or []), + "prompt_ids": getattr(attr, "prompt_ids", None).detach().cpu().tolist() if getattr(attr, "prompt_ids", None) is not None else None, + "generation_ids": getattr(attr, "generation_ids", None).detach().cpu().tolist() if getattr(attr, "generation_ids", None) is not None else None, + } + + raw_vectors = [] + if result.metadata and "ifr" in result.metadata: + raw_ifr = result.metadata["ifr"].get("raw") + if raw_ifr is not None and hasattr(raw_ifr, "raw_attributions"): + try: + raw_vectors = [r.token_importance_total.detach().cpu() for r in raw_ifr.raw_attributions] + except Exception: + raw_vectors = [] + debug_info["raw_hop_vectors"] = raw_vectors + + return result, sink, thinking, debug_info + + +def run_ft_multihop_split_hop( + example: ds_utils.CachedExample, + model: Any, + tokenizer: Any, + *, + n_hops: int, + sink_span: Optional[Sequence[int]], + thinking_span: Optional[Sequence[int]], + chunk_tokens: int, + sink_chunk_tokens: int, +) -> Tuple[Any, Optional[Tuple[int, int]], Optional[Tuple[int, int]], Dict[str, Any]]: + """Execute experimental FT (split-hop IFR over segmented thinking span).""" + + import ft_ifr_improve + + attr = ft_ifr_improve.LLMIFRAttributionSplitHop( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + + sink = tuple(sink_span) if sink_span is not None else tuple(example.sink_span) if example.sink_span else None + thinking = ( + tuple(thinking_span) + if thinking_span is not None + else tuple(example.thinking_span) if example.thinking_span else None + ) + + result = attr.calculate_ifr_multi_hop_split_hop( + example.prompt, + target=example.target, + sink_span=sink, + thinking_span=thinking, + n_hops=int(n_hops), + ) + + debug_info: Dict[str, Any] = { + "full_prompt_tokens": list(getattr(attr, "prompt_tokens", []) or []), + "generation_tokens": list(getattr(attr, "generation_tokens", []) or []), + "user_prompt_indices": list(getattr(attr, "user_prompt_indices", []) or []), + "chat_prompt_indices": list(getattr(attr, "chat_prompt_indices", []) or []), + "prompt_ids": getattr(attr, "prompt_ids", None).detach().cpu().tolist() if getattr(attr, "prompt_ids", None) is not None else None, + "generation_ids": getattr(attr, "generation_ids", None).detach().cpu().tolist() if getattr(attr, "generation_ids", None) is not None else None, + } + + raw_vectors = [] + if result.metadata and "ifr" in result.metadata: + raw_ifr = result.metadata["ifr"].get("raw") + if raw_ifr is not None and hasattr(raw_ifr, "raw_attributions"): + try: + raw_vectors = [r.token_importance_total.detach().cpu() for r in raw_ifr.raw_attributions] + except Exception: + raw_vectors = [] + debug_info["raw_hop_vectors"] = raw_vectors + + return result, sink, thinking, debug_info + + +def run_ifr_in_all_gen( + example: ds_utils.CachedExample, + model: Any, + tokenizer: Any, + *, + n_hops: int, + sink_span: Optional[Sequence[int]], + thinking_span: Optional[Sequence[int]], + chunk_tokens: int, + sink_chunk_tokens: int, +) -> Tuple[Any, Optional[Tuple[int, int]], Optional[Tuple[int, int]], Dict[str, Any]]: + """Execute experimental IFR variant: multi-hop over all generation (CoT + output).""" + + import ft_ifr_improve + + attr = ft_ifr_improve.LLMIFRAttributionInAllGen( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + + sink = tuple(sink_span) if sink_span is not None else tuple(example.sink_span) if example.sink_span else None + thinking = ( + tuple(thinking_span) + if thinking_span is not None + else tuple(example.thinking_span) if example.thinking_span else None + ) + + result = attr.calculate_ifr_in_all_gen( + example.prompt, + target=example.target, + sink_span=sink, + thinking_span=thinking, + n_hops=int(n_hops), + ) + + debug_info: Dict[str, Any] = { + "full_prompt_tokens": list(getattr(attr, "prompt_tokens", []) or []), + "generation_tokens": list(getattr(attr, "generation_tokens", []) or []), + "user_prompt_indices": list(getattr(attr, "user_prompt_indices", []) or []), + "chat_prompt_indices": list(getattr(attr, "chat_prompt_indices", []) or []), + "prompt_ids": getattr(attr, "prompt_ids", None).detach().cpu().tolist() if getattr(attr, "prompt_ids", None) is not None else None, + "generation_ids": getattr(attr, "generation_ids", None).detach().cpu().tolist() if getattr(attr, "generation_ids", None) is not None else None, + } + + raw_vectors = [] + if result.metadata and "ifr" in result.metadata: + raw_ifr = result.metadata["ifr"].get("raw") + if raw_ifr is not None and hasattr(raw_ifr, "raw_attributions"): + try: + raw_vectors = [r.token_importance_total.detach().cpu() for r in raw_ifr.raw_attributions] + except Exception: + raw_vectors = [] + debug_info["raw_hop_vectors"] = raw_vectors + + return result, sink, thinking, debug_info + + +def make_output_stem(dataset_name: str, index: int, mode: str) -> str: + safe_name = dataset_name.replace("/", "_").replace(" ", "_") + prefix = { + "ft": "ft_case_", + "ft_improve": "ft_improve_case_", + "ifr": "ifr_case_", + "ifr_all_positions": "ifr_all_positions_case_", + "ifr_all_positions_output_only": "ifr_output_only_case_", + "attnlrp": "attnlrp_case_", + "ft_attnlrp": "ft_attnlrp_case_", + }.get(mode, f"{mode}_case_") + return f"{prefix}{safe_name}_idx{index}" + + +def _decode_token_ids(tokenizer: Any, ids: Sequence[int]) -> List[str]: + """Decode each token id into a readable text piece (keeps special tokens).""" + + pieces: List[str] = [] + for tok_id in ids: + try: + pieces.append( + tokenizer.decode([int(tok_id)], skip_special_tokens=False, clean_up_tokenization_spaces=False) + ) + except Exception: + pieces.append(str(tok_id)) + return pieces + + +def build_raw_tokens_from_ids(tokenizer: Any, prompt_ids: Optional[Sequence[int]], generation_ids: Optional[Sequence[int]]) -> List[str]: + if not prompt_ids: + prompt_ids = [] + if not generation_ids: + generation_ids = [] + return _decode_token_ids(tokenizer, prompt_ids) + _decode_token_ids(tokenizer, generation_ids) + + +def build_trimmed_roles(tokens: Sequence[str], segments: Dict[str, Any]) -> List[str]: + """Assign role labels for trimmed tokens (prompt + generation).""" + + roles = ["prompt" for _ in range(len(tokens))] + prompt_len_tokens = segments.get("prompt_len", 0) + for idx in range(prompt_len_tokens, len(tokens)): + roles[idx] = "gen" + thinking_span = segments.get("thinking_span") + sink_span = segments.get("sink_span") + if thinking_span is not None: + start = prompt_len_tokens + int(thinking_span[0]) + end = prompt_len_tokens + int(thinking_span[1]) + for i in range(start, min(len(tokens), end + 1)): + roles[i] = "think" + if sink_span is not None: + start = prompt_len_tokens + int(sink_span[0]) + end = prompt_len_tokens + int(sink_span[1]) + for i in range(start, min(len(tokens), end + 1)): + roles[i] = "output" + return roles + + +def build_raw_roles( + tokens: Sequence[str], + prompt_len_full: int, + user_indices: Sequence[int], + template_indices: Sequence[int], + thinking_span_abs: Optional[Sequence[int]], + sink_span_abs: Optional[Sequence[int]], +) -> List[str]: + """Assign role labels for raw tokens (template + user + generation).""" + + roles = ["template" for _ in range(len(tokens))] + user_set = set(int(i) for i in user_indices) + tmpl_set = set(int(i) for i in template_indices) + + for i in range(min(len(tokens), prompt_len_full)): + if i in user_set: + roles[i] = "user" + elif i in tmpl_set: + roles[i] = "template" + else: + roles[i] = "prompt" + + for i in range(prompt_len_full, len(tokens)): + roles[i] = "gen" + + if thinking_span_abs is not None: + start, end = int(thinking_span_abs[0]), int(thinking_span_abs[1]) + for i in range(start, min(len(tokens), end + 1)): + roles[i] = "think" + + if sink_span_abs is not None: + start, end = int(sink_span_abs[0]), int(sink_span_abs[1]) + for i in range(start, min(len(tokens), end + 1)): + roles[i] = "output" + + return roles + + +def extract_prompt_only_vectors(hop_vectors: Sequence[torch.Tensor], prompt_len: int) -> List[torch.Tensor]: + """Slice hop vectors down to user-prompt tokens only (no generation tokens).""" + + if prompt_len < 0: + raise ValueError("prompt_len must be >= 0.") + + out: List[torch.Tensor] = [] + for vec in hop_vectors: + v = torch.as_tensor(vec, dtype=torch.float32).detach().cpu() + if int(v.numel()) < int(prompt_len): + raise ValueError(f"Hop vector too short for prompt-only slice: len={int(v.numel())} prompt_len={int(prompt_len)}.") + out.append(v[:prompt_len]) + return out + + +def _lift_trimmed_to_full( + trimmed: torch.Tensor, + *, + prompt_len_full: int, + gen_len: int, + user_prompt_indices: Sequence[int], +) -> torch.Tensor: + """Lift a trimmed (user prompt + generation) vector into full token space with zeros for chat-template tokens.""" + + t = torch.as_tensor(trimmed, dtype=torch.float32).detach().cpu() + user_len = len(user_prompt_indices) + expected = int(user_len + gen_len) + if int(t.numel()) != expected: + raise ValueError(f"Trimmed vector length mismatch: got {int(t.numel())}, expected {expected}.") + + total_len = int(prompt_len_full + gen_len) + full = torch.zeros((total_len,), dtype=torch.float32) + for j, abs_pos in enumerate(user_prompt_indices): + full[int(abs_pos)] = t[j] + full[int(prompt_len_full) : int(prompt_len_full + gen_len)] = t[user_len:] + return full + + +def _postprocess_attnlrp_full_vector( + raw_full: torch.Tensor, + *, + prompt_len_full: int, + gen_len: int, + user_prompt_indices: Sequence[int], + neg_handling: str, + norm_mode: str, +) -> torch.Tensor: + """Mirror FT-AttnLRP hop postprocessing while preserving stripped-token normalization. + + The underlying AttnLRP implementation postprocesses the *stripped* vector (user prompt + generation): + - NaN->0, then neg_handling ('drop' or 'abs') + - if norm_mode=='norm': normalize by sum over stripped tokens + + For the pre-trim full view (chat template + generation), we apply the same non-negativity transform + to the full vector and normalize using *only the stripped indices*, so overlapping token scores + match the trimmed vectors used by the evaluation/case-study hop outputs. + """ + + v = torch.as_tensor(raw_full, dtype=torch.float32).detach().cpu() + v = torch.nan_to_num(v, nan=0.0) + + if neg_handling == "drop": + v = v.clamp(min=0.0) + elif neg_handling == "abs": + v = v.abs() + else: + raise ValueError(f"Unsupported neg_handling={neg_handling!r} (expected 'drop' or 'abs').") + + ratio_enabled = norm_mode == "norm" + if not ratio_enabled: + return v + + keep = list(int(i) for i in user_prompt_indices) + list(range(int(prompt_len_full), int(prompt_len_full + gen_len))) + if not keep: + return torch.zeros_like(v) + + keep_idx = torch.as_tensor(keep, dtype=torch.long) + denom = float(v.index_select(0, keep_idx).sum().item()) + if denom <= 0.0: + return torch.zeros_like(v) + return v / (denom + 1e-12) + + +def main() -> None: + args = parse_args() + device = resolve_device(args.cuda, args.cuda_num) + if torch.cuda.is_available(): + visible = os.environ.get("CUDA_VISIBLE_DEVICES") + print(f"[info] CUDA_VISIBLE_DEVICES={visible!r} torch.cuda.device_count()={torch.cuda.device_count()} device={device}") + + model_name = args.model_path if args.model_path is not None else args.model + # Align with exp/exp2: always use the shared fp16 loader. + model, tokenizer = load_model(model_name, device) + + example, ds_name = load_example(args.dataset, args.index, Path(args.data_root)) + mode = args.mode + + sink_span: Optional[Tuple[int, int]] = None + thinking_span: Optional[Tuple[int, int]] = None + thinking_ratios: Optional[Sequence[float]] = None + + prompt_tokens_trimmed: List[str] = [] + generation_tokens_trimmed: List[str] = [] + hop_vectors_trimmed: List[torch.Tensor] = [] + hop_vectors_raw: List[torch.Tensor] = [] + prompt_len_full: Optional[int] = None + user_prompt_indices: List[int] = [] + chat_prompt_indices: List[int] = [] + method_meta: Dict[str, Any] = {} + raw_prompt_ids: Optional[List[int]] = None + raw_generation_ids: Optional[List[int]] = None + attnlrp_raw_attributions: Optional[List[Any]] = None + + if mode in ("ft", "ft_improve", "ft_split_hop", "ifr_in_all_gen"): + if mode == "ft": + attr_result, sink_span, thinking_span, debug_info = run_ft_multihop( + example, + model, + tokenizer, + n_hops=args.n_hops, + sink_span=args.sink_span, + thinking_span=args.thinking_span, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + ) + elif mode == "ft_improve": + attr_result, sink_span, thinking_span, debug_info = run_ft_multihop_improve( + example, + model, + tokenizer, + n_hops=args.n_hops, + sink_span=args.sink_span, + thinking_span=args.thinking_span, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + ) + elif mode == "ft_split_hop": + attr_result, sink_span, thinking_span, debug_info = run_ft_multihop_split_hop( + example, + model, + tokenizer, + n_hops=args.n_hops, + sink_span=args.sink_span, + thinking_span=args.thinking_span, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + ) + elif mode == "ifr_in_all_gen": + attr_result, sink_span, thinking_span, debug_info = run_ifr_in_all_gen( + example, + model, + tokenizer, + n_hops=args.n_hops, + sink_span=args.sink_span, + thinking_span=args.thinking_span, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + ) + else: + raise ValueError(f"Unsupported mode={mode}") + ifr_meta = (attr_result.metadata or {}).get("ifr") or {} + hop_vectors_trimmed = list(ifr_meta.get("per_hop_projected") or []) + if not hop_vectors_trimmed: + raise RuntimeError(f"No per-hop vectors found for {mode} mode.") + + prompt_tokens_trimmed = list(attr_result.prompt_tokens) + generation_tokens_trimmed = list(attr_result.generation_tokens) + thinking_ratios = ifr_meta.get("thinking_ratios") + + raw_prompt_ids = debug_info.get("prompt_ids") + if isinstance(raw_prompt_ids, list) and raw_prompt_ids and isinstance(raw_prompt_ids[0], list): + raw_prompt_ids = raw_prompt_ids[0] + raw_generation_ids = debug_info.get("generation_ids") + if isinstance(raw_generation_ids, list) and raw_generation_ids and isinstance(raw_generation_ids[0], list): + raw_generation_ids = raw_generation_ids[0] + + user_prompt_indices = list(debug_info.get("user_prompt_indices") or []) + chat_prompt_indices = list(debug_info.get("chat_prompt_indices") or []) + prompt_len_full = len(raw_prompt_ids) if isinstance(raw_prompt_ids, list) else None + + raw_vectors = debug_info.get("raw_hop_vectors") or [] + hop_vectors_raw = [vec.detach().cpu() if hasattr(vec, "detach") else torch.as_tensor(vec) for vec in raw_vectors] + method_meta = {"ifr": analysis.sanitize_ifr_meta(ifr_meta)} + + elif mode == "ifr": + # Standard IFR (single-hop span aggregate), with pre/post trim views. + attr = llm_attr.LLMIFRAttribution( + model, + tokenizer, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + ) + sink_span = tuple(args.sink_span) if args.sink_span is not None else tuple(example.sink_span) if example.sink_span else None + thinking_span = tuple(args.thinking_span) if args.thinking_span is not None else tuple(example.thinking_span) if example.thinking_span else sink_span + + if sink_span is None: + raise ValueError("sink_span is required for IFR mode (use dataset sink_span or pass --sink_span).") + span_result = attr.calculate_ifr_span( + example.prompt, + target=example.target, + span=tuple(sink_span), + ) + span_meta = span_result.metadata.get("ifr") if span_result.metadata else None + aggregate = span_meta.get("aggregate") if isinstance(span_meta, dict) else None + if aggregate is None or not hasattr(aggregate, "token_importance_total"): + raise RuntimeError("IFR span aggregate missing from metadata; cannot render pre-trim view.") + + raw_vector = aggregate.token_importance_total.detach().cpu() + trimmed_vector = attr._project_vector(raw_vector) + hop_vectors_raw = [raw_vector] + hop_vectors_trimmed = [trimmed_vector] + + prompt_tokens_trimmed = list(attr.user_prompt_tokens) + generation_tokens_trimmed = list(attr.generation_tokens) + + raw_prompt_ids = attr.prompt_ids.detach().cpu().tolist()[0] + raw_generation_ids = attr.generation_ids.detach().cpu().tolist()[0] + user_prompt_indices = list(getattr(attr, "user_prompt_indices", []) or []) + chat_prompt_indices = list(getattr(attr, "chat_prompt_indices", []) or []) + prompt_len_full = len(raw_prompt_ids) + + sink_abs = (prompt_len_full + sink_span[0], prompt_len_full + sink_span[1]) + think_abs = (prompt_len_full + thinking_span[0], prompt_len_full + thinking_span[1]) if thinking_span else None + + meta = { + "type": "span_aggregate", + "ifr_view": "aggregate", + "sink_span_generation": sink_span, + "sink_span_absolute": sink_abs, + "thinking_span_generation": thinking_span, + "thinking_span_absolute": think_abs, + } + method_meta = {"ifr": analysis.tensor_to_list(meta)} + + elif mode == "ifr_all_positions_output_only": + # IFR all-positions (output-only) + token-level CAGE (row/recursive) derived from the matrix. + attr = llm_attr.LLMIFRAttribution( + model, + tokenizer, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + ) + sink_span = tuple(args.sink_span) if args.sink_span is not None else tuple(example.sink_span) if example.sink_span else None + thinking_span = tuple(args.thinking_span) if args.thinking_span is not None else tuple(example.thinking_span) if example.thinking_span else sink_span + + if sink_span is None: + raise ValueError( + "sink_span is required for ifr_all_positions_output_only mode " + "(use dataset sink_span or pass --sink_span)." + ) + + attr_result = attr.calculate_ifr_for_all_positions_output_only( + example.prompt, + target=example.target, + sink_span=tuple(sink_span), + ) + + indices_to_explain = list(sink_span) + _, row_attr, rec_attr = attr_result.get_all_token_attrs(indices_to_explain) + row_vec = row_attr.squeeze(0).detach().cpu() + rec_vec = rec_attr.squeeze(0).detach().cpu() + + hop_vectors_trimmed = [row_vec, rec_vec] + + prompt_tokens_trimmed = list(attr.user_prompt_tokens) + generation_tokens_trimmed = list(attr.generation_tokens) + + raw_prompt_ids = attr.prompt_ids.detach().cpu().tolist()[0] + raw_generation_ids = attr.generation_ids.detach().cpu().tolist()[0] + user_prompt_indices = list(getattr(attr, "user_prompt_indices", []) or []) + chat_prompt_indices = list(getattr(attr, "chat_prompt_indices", []) or []) + prompt_len_full = len(raw_prompt_ids) + + gen_len = len(raw_generation_ids or []) + hop_vectors_raw = [ + _lift_trimmed_to_full( + v, + prompt_len_full=int(prompt_len_full or 0), + gen_len=gen_len, + user_prompt_indices=user_prompt_indices, + ) + for v in hop_vectors_trimmed + ] + + ifr_meta = dict((attr_result.metadata or {}).get("ifr") or {}) + ifr_meta["ifr_view"] = "all_positions_output_only (row+rec)" + ifr_meta["panel_titles"] = ["Row attribution", "Recursive attribution (CAGE)"] + ifr_meta["indices_to_explain"] = indices_to_explain + method_meta = {"ifr": analysis.tensor_to_list(ifr_meta)} + + elif mode == "ifr_all_positions": + # IFR all-positions (full generation) + token-level CAGE (row/recursive) derived from the matrix. + attr = llm_attr.LLMIFRAttribution( + model, + tokenizer, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + ) + sink_span = tuple(args.sink_span) if args.sink_span is not None else tuple(example.sink_span) if example.sink_span else None + thinking_span = tuple(args.thinking_span) if args.thinking_span is not None else tuple(example.thinking_span) if example.thinking_span else sink_span + + if sink_span is None: + raise ValueError( + "sink_span is required for ifr_all_positions mode (use dataset sink_span or pass --sink_span)." + ) + + attr_result = attr.calculate_ifr_for_all_positions( + example.prompt, + target=example.target, + ) + + indices_to_explain = list(sink_span) + _, row_attr, rec_attr = attr_result.get_all_token_attrs(indices_to_explain) + row_vec = row_attr.squeeze(0).detach().cpu() + rec_vec = rec_attr.squeeze(0).detach().cpu() + + hop_vectors_trimmed = [row_vec, rec_vec] + + prompt_tokens_trimmed = list(attr.user_prompt_tokens) + generation_tokens_trimmed = list(attr.generation_tokens) + + raw_prompt_ids = attr.prompt_ids.detach().cpu().tolist()[0] + raw_generation_ids = attr.generation_ids.detach().cpu().tolist()[0] + user_prompt_indices = list(getattr(attr, "user_prompt_indices", []) or []) + chat_prompt_indices = list(getattr(attr, "chat_prompt_indices", []) or []) + prompt_len_full = len(raw_prompt_ids) + + gen_len = len(raw_generation_ids or []) + hop_vectors_raw = [ + _lift_trimmed_to_full( + v, + prompt_len_full=int(prompt_len_full or 0), + gen_len=gen_len, + user_prompt_indices=user_prompt_indices, + ) + for v in hop_vectors_trimmed + ] + + ifr_meta = dict((attr_result.metadata or {}).get("ifr") or {}) + ifr_meta["ifr_view"] = "all_positions (row+rec)" + ifr_meta["panel_titles"] = ["Row attribution", "Recursive attribution (CAGE)"] + ifr_meta["indices_to_explain"] = indices_to_explain + method_meta = {"ifr": analysis.tensor_to_list(ifr_meta)} + + elif mode in ("attnlrp", "ft_attnlrp"): + # Reuse the shared LLMLRPAttribution implementations (root-level). + attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + + sink_span = tuple(args.sink_span) if args.sink_span is not None else tuple(example.sink_span) if example.sink_span else None + thinking_span = ( + tuple(args.thinking_span) + if args.thinking_span is not None + else tuple(example.thinking_span) if example.thinking_span else sink_span + ) + + if mode == "attnlrp": + # Case-study AttnLRP: reuse FT-AttnLRP logic but take hop0 (the first span-aggregate) + # for a full, signed attribution vector (no observation masking). + attr_result = attributor.calculate_attnlrp_ft_hop0( + example.prompt, + target=example.target, + sink_span=sink_span, + thinking_span=thinking_span, + neg_handling=args.attnlrp_neg_handling, + norm_mode=args.attnlrp_norm_mode, + ) + meta = attr_result.metadata or {} + multi_hop = meta.get("multi_hop_result") + raw_attributions = getattr(multi_hop, "raw_attributions", None) or [] + attnlrp_raw_attributions = list(raw_attributions) + base_attr = raw_attributions[0] if raw_attributions else None + if base_attr is None or not hasattr(base_attr, "token_importance_total"): + raise RuntimeError("AttnLRP hop0 missing from multi-hop result.") + + hop0_vec = torch.as_tensor(getattr(base_attr, "token_importance_total"), dtype=torch.float32).detach().cpu() + if hop0_vec.numel() <= 0: + raise RuntimeError("Empty generation for AttnLRP case study.") + + # Use the actual sink span applied by hop0 (defaults to full generation when unset). + sink_span = tuple(getattr(base_attr, "sink_range")) + if thinking_span is None: + thinking_span = sink_span + + hop_vectors_trimmed = [hop0_vec] + thinking_ratios = list(getattr(multi_hop, "thinking_ratios", []) or []) + + method_meta = { + "attnlrp": { + "type": "calculate_attnlrp_multi_hop(n_hops=0) hop0 raw_attributions[0]", + "sink_span_generation": sink_span, + "thinking_span_generation": thinking_span, + "thinking_ratios": thinking_ratios, + "neg_handling": args.attnlrp_neg_handling, + "norm_mode": args.attnlrp_norm_mode, + "ratio_enabled": args.attnlrp_norm_mode == "norm", + } + } + else: + # exp2 ft_attnlrp: multi-hop aggregated AttnLRP (metadata contains per-hop vectors). + attr_result = attributor.calculate_attnlrp_aggregated_multi_hop( + example.prompt, + target=example.target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(args.n_hops), + neg_handling=args.attnlrp_neg_handling, + norm_mode=args.attnlrp_norm_mode, + ) + meta = attr_result.metadata or {} + multi_hop = meta.get("multi_hop_result") + if multi_hop is None: + raise RuntimeError("FT-AttnLRP case study missing metadata.multi_hop_result.") + + raw_attributions = getattr(multi_hop, "raw_attributions", None) or [] + attnlrp_raw_attributions = list(raw_attributions) + hop_vectors_trimmed = [ + torch.as_tensor(getattr(hop, "token_importance_total"), dtype=torch.float32).detach().cpu() + for hop in raw_attributions + ] + thinking_ratios = list(getattr(multi_hop, "thinking_ratios", []) or []) + + method_meta = { + "attnlrp": { + "type": "calculate_attnlrp_aggregated_multi_hop (exp2 ft_attnlrp)", + "n_hops": int(args.n_hops), + "sink_span_generation": sink_span, + "thinking_span_generation": thinking_span, + "thinking_ratios": thinking_ratios, + "neg_handling": args.attnlrp_neg_handling, + "norm_mode": args.attnlrp_norm_mode, + "ratio_enabled": args.attnlrp_norm_mode == "norm", + } + } + + prompt_tokens_trimmed = list(attributor.user_prompt_tokens) + generation_tokens_trimmed = list(attributor.generation_tokens) + + raw_prompt_ids = attributor.prompt_ids.detach().cpu().tolist()[0] + raw_generation_ids = attributor.generation_ids.detach().cpu().tolist()[0] + user_prompt_indices = list(getattr(attributor, "user_prompt_indices", []) or []) + chat_prompt_indices = list(getattr(attributor, "chat_prompt_indices", []) or []) + prompt_len_full = len(raw_prompt_ids) + + else: + raise ValueError(f"Unsupported mode={mode}") + + if not hop_vectors_trimmed: + raise RuntimeError("No hop vectors to visualize.") + + raw_tokens = build_raw_tokens_from_ids(tokenizer, raw_prompt_ids, raw_generation_ids) + + sink_span_abs = None + thinking_span_abs = None + if prompt_len_full is not None and sink_span is not None: + sink_span_abs = (prompt_len_full + sink_span[0], prompt_len_full + sink_span[1]) + if prompt_len_full is not None and thinking_span is not None: + thinking_span_abs = (prompt_len_full + thinking_span[0], prompt_len_full + thinking_span[1]) + prompt_len_full_safe = int(prompt_len_full or 0) + roles_raw = build_raw_roles( + raw_tokens, + prompt_len_full_safe, + user_prompt_indices, + chat_prompt_indices, + thinking_span_abs, + sink_span_abs, + ) + + prompt_tokens_only = list(prompt_tokens_trimmed) + prompt_only_vectors = extract_prompt_only_vectors(hop_vectors_trimmed, len(prompt_tokens_only)) + + # Ensure every method has a pre-trim full vector per panel. + if not hop_vectors_raw: + if mode in ("attnlrp", "ft_attnlrp") and attnlrp_raw_attributions is not None: + gen_len = len(raw_generation_ids or []) + expected = int((prompt_len_full_safe + gen_len) if prompt_len_full is not None else 0) + full_vectors: List[torch.Tensor] = [] + for hop in attnlrp_raw_attributions: + meta = getattr(hop, "metadata", None) or {} + raw_full = meta.get("token_importance_total_with_chat_template") + if raw_full is None: + full_vectors = [] + break + v = _postprocess_attnlrp_full_vector( + torch.as_tensor(raw_full, dtype=torch.float32), + prompt_len_full=prompt_len_full_safe, + gen_len=gen_len, + user_prompt_indices=user_prompt_indices, + neg_handling=args.attnlrp_neg_handling, + norm_mode=args.attnlrp_norm_mode, + ) + if expected and int(v.numel()) != expected: + raise RuntimeError( + "AttnLRP full-vector length mismatch for pre-trim view: " + f"got {int(v.numel())}, expected {expected}." + ) + full_vectors.append(v) + hop_vectors_raw = full_vectors + + if not hop_vectors_raw and prompt_len_full is not None: + # Fallback: lift trimmed vectors back to full token space with zeros for template tokens. + gen_len = len(raw_generation_ids or []) + hop_vectors_raw = [ + _lift_trimmed_to_full( + v, + prompt_len_full=prompt_len_full_safe, + gen_len=gen_len, + user_prompt_indices=user_prompt_indices, + ) + for v in hop_vectors_trimmed + ] + + if not hop_vectors_raw: + raise RuntimeError("Missing pre-trim vectors; cannot render required full-sequence heatmap.") + + # Lightweight debug stats to catch silent all-zero / NaN cases. + hop_stats_raw = [analysis.vector_stats(torch.nan_to_num(v.detach().cpu(), nan=0.0)) for v in hop_vectors_raw] + hop_stats_prompt = [analysis.vector_stats(torch.nan_to_num(v.detach().cpu(), nan=0.0)) for v in prompt_only_vectors] + for i in range(max(len(hop_stats_raw), len(hop_stats_prompt))): + raw_abs = hop_stats_raw[i]["abs_max"] if i < len(hop_stats_raw) else None + prompt_abs = hop_stats_prompt[i]["abs_max"] if i < len(hop_stats_prompt) else None + print(f"[stats] panel {i}: raw_abs_max={raw_abs} prompt_abs_max={prompt_abs}") + + hop_token_raw = analysis.package_token_hops(hop_vectors_raw) + hop_token_prompt = analysis.package_token_hops(prompt_only_vectors) + + case_meta: Dict[str, Any] = { + "dataset": ds_name, + "index": args.index, + "sink_span": sink_span, + "thinking_span": thinking_span, + "n_hops": args.n_hops, + "thinking_ratios": thinking_ratios, + "mode": mode, + "ifr_view": method_meta.get("ifr", {}).get("ifr_view") if isinstance(method_meta.get("ifr"), dict) else None, + "panel_titles": method_meta.get("ifr", {}).get("panel_titles") if isinstance(method_meta.get("ifr"), dict) else None, + "attnlrp_neg_handling": args.attnlrp_neg_handling if mode in ("attnlrp", "ft_attnlrp") else None, + "attnlrp_norm_mode": args.attnlrp_norm_mode if mode in ("attnlrp", "ft_attnlrp") else None, + "attnlrp_ratio_enabled": (args.attnlrp_norm_mode == "norm") if mode in ("attnlrp", "ft_attnlrp") else None, + "vector_stats_raw": hop_stats_raw, + "vector_stats_prompt": hop_stats_prompt, + } + + generation_text = "".join(generation_tokens_trimmed) if generation_tokens_trimmed else "" + prompt_text = example.prompt + record = { + "meta": case_meta, + "prompt": prompt_text, + "target": example.target, + "generation": generation_text, + "full_all_tokens": raw_tokens, + "raw_token_roles": roles_raw, + "prompt_tokens": prompt_tokens_only, + "prompt_token_roles": ["user" for _ in range(len(prompt_tokens_only))], + "token_hops_raw": hop_token_raw, + "token_hops_prompt": hop_token_prompt, + "ifr_meta": method_meta.get("ifr"), + "attnlrp_meta": method_meta.get("attnlrp"), + } + + out_dir = Path(args.output_dir) + out_dir.mkdir(parents=True, exist_ok=True) + stem = make_output_stem(ds_name, args.index, mode) + json_path = out_dir / f"{stem}.json" + html_path = out_dir / f"{stem}.html" + + with json_path.open("w", encoding="utf-8") as f: + json.dump(record, f, ensure_ascii=False, indent=2) + + html = viz.render_case_html( + case_meta, + token_view_raw={ + "label": "Pre-trim token-level heatmap (full sequence with chat template)", + "tokens": raw_tokens, + "roles": roles_raw, + "hops": hop_token_raw, + }, + token_view_prompt={ + "label": "Prompt-only token-level heatmap (user prompt only)", + "tokens": prompt_tokens_only, + "roles": ["user" for _ in range(len(prompt_tokens_only))], + "hops": hop_token_prompt, + }, + ) + html_path.write_text(html, encoding="utf-8") + + print(f"[done] wrote {json_path}") + print(f"[done] wrote {html_path}") + + +if __name__ == "__main__": + main() diff --git a/exp/case_study/run_mas_case.py b/exp/case_study/run_mas_case.py new file mode 100644 index 0000000000000000000000000000000000000000..020434830178d612d969cc60caff2a5c15317198 --- /dev/null +++ b/exp/case_study/run_mas_case.py @@ -0,0 +1,805 @@ +#!/usr/bin/env python3 +"""MAS case study: visualize token-perturbation faithfulness for attribution methods. + +This script matches the faithfulness evaluation logic implemented in: + - evaluations/faithfulness.py + - llm_attr_eval.LLMAttributionEvaluator.faithfulness_test() + +For a single example and a selected attribution method, we: + 1) Compute token-level attributions (Seq / Row / Recursive) over prompt tokens. + 2) Rank prompt tokens by attribution mass. + 3) Iteratively perturb the prompt by replacing one token at a time with PAD tokens. + 4) Score the model as sum log p(generation + EOS | prompt) under the chat template. + 5) Compute RISE / MAS / RISE+AP (AUCs) and visualize the perturbation impact as token heatmaps. + +Outputs JSON + HTML to exp/case_study/out/. +""" + +from __future__ import annotations + +import argparse +import json +import os +import sys +import types +from importlib.machinery import ModuleSpec +from pathlib import Path +from typing import Any, Dict, List, Optional, Sequence, Tuple + +import numpy as np + + +def _early_set_cuda_visible_devices() -> None: + """Set CUDA_VISIBLE_DEVICES before importing torch/transformers. + + Note: CUDA device indices are re-mapped inside the process after applying the mask. + """ + + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("--cuda", type=str, default=None) + args, _ = parser.parse_known_args(sys.argv[1:]) + cuda = args.cuda.strip() if isinstance(args.cuda, str) else "" + if cuda and "," in cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = cuda + + +if __name__ == "__main__": + _early_set_cuda_visible_devices() + +import torch + +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + +# Avoid optional vision deps when importing transformers. +os.environ.setdefault("TRANSFORMERS_NO_TORCHVISION", "1") +os.environ.setdefault("DISABLE_TRANSFORMERS_IMAGE_TRANSFORMS", "1") + + +def _stub_torchvision() -> None: + """Provide minimal torchvision stubs so transformers imports succeed without torchvision.""" + + if "torchvision" in sys.modules: + return + + def _mk(name: str) -> types.ModuleType: + mod = types.ModuleType(name) + mod.__spec__ = ModuleSpec(name, loader=None) + return mod + + tv = _mk("torchvision") + tv.__dict__["__path__"] = [] + submods = ["transforms", "_meta_registrations", "datasets", "io", "models", "ops", "utils"] + for name in submods: + mod = _mk(f"torchvision.{name}") + sys.modules[f"torchvision.{name}"] = mod + setattr(tv, name, mod) + + class _InterpolationMode: + NEAREST = 0 + NEAREST_EXACT = 0 + BILINEAR = 1 + BICUBIC = 2 + LANCZOS = 3 + BOX = 4 + HAMMING = 5 + + sys.modules["torchvision.transforms"].InterpolationMode = _InterpolationMode + sys.modules["torchvision.transforms"].__all__ = ["InterpolationMode"] + + ops_mod = sys.modules.get("torchvision.ops") or _mk("torchvision.ops") + sys.modules["torchvision.ops"] = ops_mod + setattr(tv, "ops", ops_mod) + misc_mod = _mk("torchvision.ops.misc") + sys.modules["torchvision.ops.misc"] = misc_mod + setattr(ops_mod, "misc", misc_mod) + + class _FrozenBatchNorm2d: + def __init__(self, *args, **kwargs): + pass + + misc_mod.FrozenBatchNorm2d = _FrozenBatchNorm2d + sys.modules["torchvision"] = tv + + +def _stub_timm() -> None: + """Provide minimal timm stubs to avoid optional vision deps.""" + + if "timm" in sys.modules: + return + + def _mk(name: str) -> types.ModuleType: + mod = types.ModuleType(name) + mod.__spec__ = ModuleSpec(name, loader=None) + return mod + + timm = _mk("timm") + timm.__dict__["__path__"] = [] + sys.modules["timm"] = timm + + data_mod = _mk("timm.data") + sys.modules["timm.data"] = data_mod + timm.data = data_mod + + class _ImageNetInfo: + pass + + def _infer_imagenet_subset(*args, **kwargs): + return None + + data_mod.ImageNetInfo = _ImageNetInfo + data_mod.infer_imagenet_subset = _infer_imagenet_subset + + layers_mod = _mk("timm.layers") + sys.modules["timm.layers"] = layers_mod + timm.layers = layers_mod + + create_norm_mod = _mk("timm.layers.create_norm") + sys.modules["timm.layers.create_norm"] = create_norm_mod + layers_mod.create_norm = create_norm_mod + + def _get_norm_layer(*args, **kwargs): + return None + + create_norm_mod.get_norm_layer = _get_norm_layer + + classifier_mod = _mk("timm.layers.classifier") + sys.modules["timm.layers.classifier"] = classifier_mod + layers_mod.classifier = classifier_mod + + +def _stub_gemma3n() -> None: + """Stub Gemma3n config module if transformers tries to import it.""" + + if "transformers.models.gemma3n.configuration_gemma3n" in sys.modules: + return + + gemma_pkg = types.ModuleType("transformers.models.gemma3n") + gemma_pkg.__spec__ = ModuleSpec("transformers.models.gemma3n", loader=None, is_package=True) + sys.modules["transformers.models.gemma3n"] = gemma_pkg + + gemma_conf = types.ModuleType("transformers.models.gemma3n.configuration_gemma3n") + gemma_conf.__spec__ = ModuleSpec("transformers.models.gemma3n.configuration_gemma3n", loader=None) + + class Gemma3nConfig: + def __init__(self, *args, **kwargs): + self.model_type = "gemma3n" + + class Gemma3nTextConfig(Gemma3nConfig): + pass + + gemma_conf.Gemma3nConfig = Gemma3nConfig + gemma_conf.Gemma3nTextConfig = Gemma3nTextConfig + gemma_conf.__all__ = ["Gemma3nConfig", "Gemma3nTextConfig"] + sys.modules["transformers.models.gemma3n.configuration_gemma3n"] = gemma_conf + setattr(gemma_pkg, "configuration_gemma3n", gemma_conf) + + +_stub_torchvision() +_stub_timm() +_stub_gemma3n() + +import transformers # noqa: E402 + +# Provide light stubs if Longformer classes are unavailable; we don't use them here. +if not hasattr(transformers, "LongformerTokenizer"): + class _DummyLongformerTokenizer: + def __init__(self, *args, **kwargs): + raise ImportError("LongformerTokenizer stubbed; install full transformers if needed.") + transformers.LongformerTokenizer = _DummyLongformerTokenizer +if not hasattr(transformers, "LongformerForMaskedLM"): + class _DummyLongformerForMaskedLM: + def __init__(self, *args, **kwargs): + raise ImportError("LongformerForMaskedLM stubbed; install full transformers if needed.") + transformers.LongformerForMaskedLM = _DummyLongformerForMaskedLM + +from exp.case_study import viz # noqa: E402 +from exp.exp2 import dataset_utils as ds_utils # noqa: E402 +from shared_utils import DEFAULT_PROMPT_TEMPLATE # noqa: E402 + +import llm_attr # noqa: E402 +from evaluations.attribution_recovery import load_model # noqa: E402 + + +def resolve_device(cuda: Optional[str], cuda_num: int) -> str: + if cuda and isinstance(cuda, str) and "," in cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = cuda + return "auto" + if cuda and isinstance(cuda, str) and cuda.strip(): + try: + idx = int(cuda) + except Exception: + idx = 0 + return f"cuda:{idx}" if torch.cuda.is_available() else "cpu" + return f"cuda:{cuda_num}" if torch.cuda.is_available() else "cpu" + + +def load_example(dataset: str, index: int, data_root: Path) -> Tuple[ds_utils.CachedExample, str]: + ds_path = Path(dataset) + if ds_path.exists(): + examples = ds_utils.read_cached_jsonl(ds_path) + dataset_name = ds_path.name + else: + loader = ds_utils.DatasetLoader(data_root=data_root) + examples = loader.load(dataset) + dataset_name = dataset + + if not examples: + raise ValueError(f"No examples found for dataset={dataset}") + + if index < 0: + index = len(examples) + index + if not (0 <= index < len(examples)): + raise IndexError(f"index {index} out of range for dataset with {len(examples)} examples") + + return examples[index], dataset_name + + +def make_output_stem(dataset_name: str, index: int, method: str) -> str: + safe_name = dataset_name.replace("/", "_").replace(" ", "_") + return f"mas_case_{method}_{safe_name}_idx{index}" + + +def format_prompt(tokenizer: Any, prompt: str) -> str: + modified_prompt = DEFAULT_PROMPT_TEMPLATE.format(context=prompt, query="") + formatted_prompt = [{"role": "user", "content": modified_prompt}] + return tokenizer.apply_chat_template( + formatted_prompt, + tokenize=False, + add_generation_prompt=True, + enable_thinking=False, + ) + + +@torch.inference_mode() +def compute_logprob_response_given_prompt(model: Any, prompt_ids: torch.Tensor, response_ids: torch.Tensor) -> torch.Tensor: + """Compute log-probabilities of response_ids given prompt_ids. + + Shapes: + prompt_ids: [B, N] + response_ids: [B, M] + returns: [B, M] + """ + input_ids = torch.cat([prompt_ids, response_ids], dim=1) + attention_mask = torch.ones_like(input_ids) + logits = model(input_ids=input_ids, attention_mask=attention_mask).logits # [B, N+M, V] + log_probs = torch.nn.functional.log_softmax(logits, dim=-1) + + response_start = int(prompt_ids.shape[1]) + logits_for_response = log_probs[:, response_start - 1 : -1, :] # [B, M, V] + gathered = logits_for_response.gather(2, response_ids.unsqueeze(-1)) + return gathered.squeeze(-1) + + +@torch.inference_mode() +def score_prompt_ids_with_generation(model: Any, *, prompt_ids: torch.Tensor, generation_ids: torch.Tensor) -> float: + return float(compute_logprob_response_given_prompt(model, prompt_ids, generation_ids).sum().detach().cpu().item()) + + +@torch.inference_mode() +def _ensure_pad_token_id(tokenizer: Any) -> int: + if tokenizer.pad_token_id is None: + if tokenizer.eos_token_id is None: + raise RuntimeError("tokenizer has neither pad_token_id nor eos_token_id; cannot define baseline token.") + tokenizer.pad_token = tokenizer.eos_token + return int(tokenizer.pad_token_id) + + +def _find_subsequence_start(haystack: torch.Tensor, needle: torch.Tensor) -> Optional[int]: + if haystack.ndim != 1 or needle.ndim != 1: + raise ValueError("Expected 1D tensors for subsequence matching.") + if needle.numel() == 0: + return 0 + hay_len = int(haystack.numel()) + needle_len = int(needle.numel()) + if needle_len > hay_len: + return None + for i in range(hay_len - needle_len + 1): + if torch.equal(haystack[i : i + needle_len], needle): + return i + return None + + +def decode_text_into_tokens(tokenizer: Any, text: str) -> List[str]: + encoding = tokenizer(text, return_offsets_mapping=True, add_special_tokens=False) + offsets = list(encoding["offset_mapping"]) + tokens: List[str] = [] + for start, end in offsets: + tokens.append(text[start:end]) + return tokens + + +def auc(arr: np.ndarray) -> float: + return float((arr.sum() - arr[0] / 2 - arr[-1] / 2) / (arr.shape[0] - 1)) + + +def mas_trace( + model: Any, + tokenizer: Any, + *, + attribution: torch.Tensor, + prompt: str, + generation: str, + user_prompt_indices: Optional[Sequence[int]] = None, + keep_prompt_token_indices: Optional[Sequence[int]] = None, + k: int = 20, +) -> Dict[str, Any]: + """Return a token-level faithfulness trace (RISE/MAS/RISE+AP) plus per-token deltas.""" + + pad_token_id = _ensure_pad_token_id(tokenizer) + + user_prompt = " " + prompt + formatted = format_prompt(tokenizer, user_prompt) + formatted_ids = tokenizer(formatted, return_tensors="pt", add_special_tokens=False).input_ids + user_ids = tokenizer(user_prompt, return_tensors="pt", add_special_tokens=False).input_ids + + prompt_ids = formatted_ids.to(model.device) + prompt_ids_perturbed = prompt_ids.clone() + gen_ids = tokenizer( + generation + (tokenizer.eos_token or ""), + return_tensors="pt", + add_special_tokens=False, + ).input_ids.to(model.device) + + attr_cpu = attribution.detach().cpu() + w = attr_cpu.sum(0) + P = int(w.numel()) + + if keep_prompt_token_indices is None: + keep = list(range(P)) + else: + keep = [] + seen: set[int] = set() + for raw in keep_prompt_token_indices: + try: + idx = int(raw) + except Exception: + continue + if 0 <= idx < P and idx not in seen: + keep.append(idx) + seen.add(idx) + keep.sort() + + K = len(keep) + if K: + w_keep = w.index_select(0, torch.as_tensor(keep, dtype=torch.long)) + sorted_local = torch.argsort(w_keep, descending=True) + sorted_attr_indices = torch.as_tensor([keep[int(i.item())] for i in sorted_local], dtype=torch.long) + attr_sum = float(w_keep.sum().item()) + else: + sorted_attr_indices = torch.zeros((0,), dtype=torch.long) + attr_sum = 0.0 + + if int(user_ids.shape[1]) != P: + raise ValueError( + "Prompt-side attribution length does not match tokenized user prompt length: " + f"attr P={P}, user_prompt P={int(user_ids.shape[1])}." + ) + + prompt_positions: List[int] + if user_prompt_indices is not None: + prompt_positions = [int(x) for x in user_prompt_indices] + if len(prompt_positions) != P: + raise ValueError( + "user_prompt_indices length does not match prompt-side attribution length: " + f"indices P={len(prompt_positions)}, attr P={P}." + ) + if P and max(prompt_positions) >= int(prompt_ids_perturbed.shape[1]): + raise ValueError("user_prompt_indices contains an out-of-bounds index for formatted prompt ids.") + else: + user_start = _find_subsequence_start(formatted_ids[0], user_ids[0]) + if user_start is None: + raise RuntimeError("Failed to locate user prompt token span inside formatted chat prompt.") + prompt_positions = [int(user_start) + j for j in range(P)] + + if K > 0: + steps = int(k) if k is not None else 0 + if steps <= 0: + steps = 1 + steps = min(steps, K) + else: + steps = 0 + + scores = np.zeros(steps + 1, dtype=np.float64) + density = np.zeros(steps + 1, dtype=np.float64) + + scores[0] = score_prompt_ids_with_generation(model, prompt_ids=prompt_ids_perturbed, generation_ids=gen_ids) + density[0] = 1.0 + + if K == 0: + return { + "num_tokens": P, + "sorted_attr_indices": [], + "scores_raw": scores.tolist(), + "density": density.tolist(), + "normalized_model_response": scores.tolist(), + "alignment_penalty": np.zeros_like(scores).tolist(), + "corrected_scores": scores.tolist(), + "token_deltas_raw": np.zeros(P, dtype=np.float64).tolist(), + "attr_weights": np.zeros(P, dtype=np.float64).tolist(), + "metrics": {"RISE": 0.0, "MAS": 0.0, "RISE+AP": 0.0}, + } + + if attr_sum <= 0: + density = np.linspace(1.0, 0.0, steps + 1) + + per_token_delta = np.zeros(P, dtype=np.float64) + + base = K // steps + remainder = K % steps + start = 0 + for step in range(steps): + size = base + (1 if step < remainder else 0) + group = sorted_attr_indices[start : start + size] + start += size + + for idx_t in group: + idx = int(idx_t.item()) + abs_pos = int(prompt_positions[idx]) + prompt_ids_perturbed[0, abs_pos] = pad_token_id + + scores[step + 1] = score_prompt_ids_with_generation(model, prompt_ids=prompt_ids_perturbed, generation_ids=gen_ids) + if attr_sum > 0: + dec = float(w.index_select(0, group).sum().item()) / attr_sum + density[step + 1] = density[step] - dec + + delta = scores[step] - scores[step + 1] + for idx_t in group: + idx = int(idx_t.item()) + per_token_delta[idx] = delta + + min_normalized_pred = 1.0 + normalized_model_response = scores.copy() + for i in range(len(scores)): + normalized_pred = (normalized_model_response[i] - scores[-1]) / (abs(scores[0] - scores[-1])) + normalized_pred = np.clip(normalized_pred, 0.0, 1.0) + min_normalized_pred = min(min_normalized_pred, float(normalized_pred)) + normalized_model_response[i] = min_normalized_pred + + alignment_penalty = np.abs(normalized_model_response - density) + corrected_scores = normalized_model_response + alignment_penalty + corrected_scores = corrected_scores.clip(0, 1) + corrected_scores = (corrected_scores - np.min(corrected_scores)) / (np.max(corrected_scores) - np.min(corrected_scores)) + if np.isnan(corrected_scores).any(): + corrected_scores = np.linspace(1, 0, len(scores)) + + rise = auc(normalized_model_response) + mas = auc(corrected_scores) + rise_ap = auc(normalized_model_response + alignment_penalty) + + if attr_sum > 0: + attr_weights = np.zeros(P, dtype=np.float64) + for idx in keep: + attr_weights[idx] = float(w[idx].item()) / (attr_sum + 1e-12) + else: + attr_weights = np.zeros(P, dtype=np.float64) + + return { + "num_tokens": P, + "sorted_attr_indices": [int(i.item()) for i in sorted_attr_indices], + "scores_raw": scores.tolist(), + "density": density.tolist(), + "normalized_model_response": normalized_model_response.tolist(), + "alignment_penalty": alignment_penalty.tolist(), + "corrected_scores": corrected_scores.tolist(), + "token_deltas_raw": per_token_delta.tolist(), + "attr_weights": attr_weights.tolist(), + "metrics": {"RISE": rise, "MAS": mas, "RISE+AP": rise_ap}, + } + + +def compute_method_attribution( + method: str, + example: ds_utils.CachedExample, + model: Any, + tokenizer: Any, + *, + n_hops: int, + sink_span: Optional[Tuple[int, int]], + thinking_span: Optional[Tuple[int, int]], + chunk_tokens: int, + sink_chunk_tokens: int, + attnlrp_neg_handling: str, + attnlrp_norm_mode: str, +) -> Tuple[str, Any, llm_attr.LLMAttributionResult]: + prompt = example.prompt + target = example.target + + if method == "ifr": + if sink_span is None: + raise ValueError("IFR requires sink_span (use dataset sink_span or pass --sink_span).") + attributor = llm_attr.LLMIFRAttribution(model, tokenizer, chunk_tokens=chunk_tokens, sink_chunk_tokens=sink_chunk_tokens) + result = attributor.calculate_ifr_span(prompt, target=target, span=sink_span) + return "IFR (ifr_span)", attributor, result + + if method == "ifr_all_positions_output_only": + if sink_span is None: + raise ValueError( + "ifr_all_positions_output_only requires sink_span (use dataset sink_span or pass --sink_span)." + ) + attributor = llm_attr.LLMIFRAttribution(model, tokenizer, chunk_tokens=chunk_tokens, sink_chunk_tokens=sink_chunk_tokens) + result = attributor.calculate_ifr_for_all_positions_output_only( + prompt, + target=target, + sink_span=sink_span, + ) + return "IFR (ifr_all_positions_output_only)", attributor, result + + if method in ("ft", "ft_ifr"): + attributor = llm_attr.LLMIFRAttribution(model, tokenizer, chunk_tokens=chunk_tokens, sink_chunk_tokens=sink_chunk_tokens) + result = attributor.calculate_ifr_multi_hop( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(n_hops), + ) + return "FT-IFR (ifr_multi_hop)", attributor, result + + if method in ("ft_improve", "ft_ifr_improve"): + import ft_ifr_improve + + attributor = ft_ifr_improve.LLMIFRAttributionImproved( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + result = attributor.calculate_ifr_multi_hop_stop_words( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(n_hops), + ) + return "FT-IFR (ifr_multi_hop_stop_words)", attributor, result + + if method == "ft_split_hop": + import ft_ifr_improve + + attributor = ft_ifr_improve.LLMIFRAttributionSplitHop( + model, + tokenizer, + chunk_tokens=chunk_tokens, + sink_chunk_tokens=sink_chunk_tokens, + ) + result = attributor.calculate_ifr_multi_hop_split_hop( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(n_hops), + ) + return "FT-IFR (ifr_multi_hop_split_hop)", attributor, result + + if method == "attnlrp": + attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + result = attributor.calculate_attnlrp_ft_hop0( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + neg_handling=attnlrp_neg_handling, + norm_mode=attnlrp_norm_mode, + ) + return "AttnLRP (ft_attnlrp hop0)", attributor, result + + if method == "ft_attnlrp": + attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + result = attributor.calculate_attnlrp_aggregated_multi_hop( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=int(n_hops), + neg_handling=attnlrp_neg_handling, + norm_mode=attnlrp_norm_mode, + ) + return "FT-AttnLRP (attnlrp_aggregated_multi_hop)", attributor, result + + raise ValueError(f"Unsupported method={method!r}") + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser("MAS case study (faithfulness perturbation visualization)") + parser.add_argument("--dataset", type=str, default="exp/exp2/data/morehopqa.jsonl", help="Dataset name or JSONL path.") + parser.add_argument("--data_root", type=str, default="exp/exp2/data", help="Cache root for dataset names.") + parser.add_argument("--index", type=int, default=0, help="Sample index (supports negative for reverse).") + parser.add_argument( + "--method", + type=str, + choices=[ + "ifr", + "ifr_all_positions_output_only", + "ft", + "ft_ifr", + "ft_improve", + "ft_ifr_improve", + "ft_split_hop", + "attnlrp", + "ft_attnlrp", + ], + default="ft", + ) + parser.add_argument("--model", type=str, default="qwen-8B", help="HF repo id (ignored if --model_path set).") + parser.add_argument("--model_path", type=str, default=None, help="Local model path to override --model.") + parser.add_argument("--cuda", type=str, default=None, help="CUDA spec (e.g., '0' or '0,1').") + parser.add_argument("--cuda_num", type=int, default=0, help="Fallback GPU index when --cuda unset.") + parser.add_argument("--n_hops", type=int, default=1, help="Number of hops for multi-hop methods.") + parser.add_argument("--sink_span", type=int, nargs=2, default=None, help="Optional sink span over generation tokens.") + parser.add_argument("--thinking_span", type=int, nargs=2, default=None, help="Optional thinking span over generation tokens.") + parser.add_argument("--chunk_tokens", type=int, default=128, help="IFR chunk size.") + parser.add_argument("--sink_chunk_tokens", type=int, default=32, help="IFR sink chunk size.") + parser.add_argument( + "--attnlrp_neg_handling", + type=str, + choices=["drop", "abs"], + default="drop", + help="FT-AttnLRP: how to handle negative values after each hop (drop=clamp>=0, abs=absolute value).", + ) + parser.add_argument( + "--attnlrp_norm_mode", + type=str, + choices=["norm", "no_norm"], + default="norm", + help="FT-AttnLRP: norm enables per-hop global+thinking normalization + ratios; no_norm disables all three.", + ) + parser.add_argument("--output_dir", type=str, default="exp/case_study/out", help="Where to write HTML/JSON artifacts.") + return parser.parse_args() + + +def main() -> None: + args = parse_args() + device = resolve_device(args.cuda, args.cuda_num) + if torch.cuda.is_available(): + visible = os.environ.get("CUDA_VISIBLE_DEVICES") + print(f"[info] CUDA_VISIBLE_DEVICES={visible!r} torch.cuda.device_count()={torch.cuda.device_count()} device={device}") + + if args.method == "ft_ifr": + method_key = "ft" + elif args.method == "ft_ifr_improve": + method_key = "ft_improve" + else: + method_key = args.method + + model_name = args.model_path if args.model_path is not None else args.model + model, tokenizer = load_model(model_name, device) + + example, ds_name = load_example(args.dataset, args.index, Path(args.data_root)) + + sink_span = tuple(args.sink_span) if args.sink_span is not None else tuple(example.sink_span) if example.sink_span else None + thinking_span = ( + tuple(args.thinking_span) + if args.thinking_span is not None + else tuple(example.thinking_span) if example.thinking_span else None + ) + + method_label, attributor, attr_result = compute_method_attribution( + method_key, + example, + model, + tokenizer, + n_hops=args.n_hops, + sink_span=sink_span, + thinking_span=thinking_span, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + attnlrp_neg_handling=args.attnlrp_neg_handling, + attnlrp_norm_mode=args.attnlrp_norm_mode, + ) + + indices_to_explain = example.indices_to_explain or example.sink_span + if not (isinstance(indices_to_explain, list) and len(indices_to_explain) == 2): + raise ValueError("MAS case study requires token-span indices_to_explain=[start_tok,end_tok] (e.g. sink_span).") + seq_attr, row_attr, rec_attr = attr_result.get_all_token_attrs(indices_to_explain) + + prompt_tokens = decode_text_into_tokens(tokenizer, " " + example.prompt) + generation_text = example.target if example.target is not None else (getattr(attributor, "generation", None) or "") + + variant_specs = [ + ("seq", "Seq attribution", seq_attr), + ("row", "Row attribution", row_attr), + ("recursive", "Recursive attribution", rec_attr), + ] + + formatted = format_prompt(tokenizer, " " + example.prompt) + prompt_ids = tokenizer(formatted, return_tensors="pt", add_special_tokens=False).input_ids.to(model.device) + gen_ids = tokenizer( + generation_text + (tokenizer.eos_token or ""), + return_tensors="pt", + add_special_tokens=False, + ).input_ids.to(model.device) + base_score = score_prompt_ids_with_generation(model, prompt_ids=prompt_ids, generation_ids=gen_ids) + + panels_raw: List[Dict[str, Any]] = [] + panels_display: List[Dict[str, Any]] = [] + + for variant_key, variant_label, variant_attr in variant_specs: + prompt_len = int(seq_attr.shape[1] - seq_attr.shape[0]) # cols=(P+G), rows=G + attr_prompt = variant_attr[:, :prompt_len] + keep_prompt_token_indices = None + if method_key == "ft_improve": + import ft_ifr_improve + + keep_prompt_token_indices = ft_ifr_improve.keep_token_indices(list(getattr(attributor, "user_prompt_tokens", []) or [])) + trace = mas_trace( + model, + tokenizer, + attribution=attr_prompt.to(device="cpu"), + prompt=example.prompt, + generation=generation_text, + user_prompt_indices=getattr(attributor, "user_prompt_indices", None), + keep_prompt_token_indices=keep_prompt_token_indices, + ) + trace["variant"] = variant_key + trace["variant_label"] = variant_label + + panel_raw = { + "variant": variant_key, + "variant_label": variant_label, + "metrics": trace.get("metrics"), + "sorted_attr_indices": trace.get("sorted_attr_indices"), + "attr_weights": trace.get("attr_weights"), + "token_deltas_raw": trace.get("token_deltas_raw"), + "mas_trace": trace, + } + panels_raw.append(panel_raw) + + panel_display = { + "variant": variant_key, + "variant_label": variant_label, + "metrics": trace.get("metrics"), + "sorted_attr_indices": trace.get("sorted_attr_indices"), + "attr_weights": trace.get("attr_weights"), + "token_deltas_raw": trace.get("token_deltas_raw"), + } + panels_display.append(panel_display) + + case_meta: Dict[str, Any] = { + "dataset": ds_name, + "index": args.index, + "mode": "mas", + "attr_method": method_key, + "attr_method_label": method_label, + "sink_span": sink_span, + "thinking_span": thinking_span, + "n_hops": int(args.n_hops), + "attnlrp_neg_handling": args.attnlrp_neg_handling if method_key in ("attnlrp", "ft_attnlrp") else None, + "attnlrp_norm_mode": args.attnlrp_norm_mode if method_key in ("attnlrp", "ft_attnlrp") else None, + "attnlrp_ratio_enabled": (args.attnlrp_norm_mode == "norm") if method_key in ("attnlrp", "ft_attnlrp") else None, + "base_score": float(base_score), + } + + record = { + "meta": case_meta, + "prompt": example.prompt, + "target": example.target, + "generation": generation_text, + "prompt_tokens": prompt_tokens, + "panels": panels_raw, + } + + out_dir = Path(args.output_dir) + out_dir.mkdir(parents=True, exist_ok=True) + stem = make_output_stem(ds_name, args.index, method_key) + json_path = out_dir / f"{stem}.json" + html_path = out_dir / f"{stem}.html" + + with json_path.open("w", encoding="utf-8") as f: + json.dump(record, f, ensure_ascii=False, indent=2) + + html = viz.render_mas_token_html( + case_meta, + prompt_tokens=prompt_tokens, + panels=panels_display, + generation=generation_text, + ) + html_path.write_text(html, encoding="utf-8") + + print(f"[done] wrote {json_path}") + print(f"[done] wrote {html_path}") + + +if __name__ == "__main__": + main() diff --git a/exp/case_study/viz.py b/exp/case_study/viz.py new file mode 100644 index 0000000000000000000000000000000000000000..704ee260ac417c7cc5ae8918d74b762b0b935947 --- /dev/null +++ b/exp/case_study/viz.py @@ -0,0 +1,647 @@ +"""HTML helpers for visualizing hop-wise IFR/AttnLRP attributions.""" + +from __future__ import annotations + +import math +from typing import Any, Dict, List, Optional, Sequence + +from html import escape + + +TOKEN_SCALE_QUANTILE = 0.995 + + +def _robust_abs_max(scores: Sequence[float], *, quantile: float = TOKEN_SCALE_QUANTILE) -> float: + """Return a robust abs max to avoid a single outlier washing out the colormap. + + Uses a high quantile (default: p99.5) over |scores|. Top outliers saturate. + """ + + abs_vals: List[float] = [] + for x in scores: + try: + v = float(x) + except Exception: + continue + if math.isnan(v): + continue + abs_vals.append(abs(v)) + + if not abs_vals: + return 0.0 + + abs_vals.sort() + q = float(quantile) + if q < 0.0: + q = 0.0 + if q > 1.0: + q = 1.0 + idx = int(q * (len(abs_vals) - 1)) + return float(abs_vals[idx]) + + +def _color_for_score(score: float, max_score: float) -> str: + if max_score <= 0: + return "background-color: rgba(245,245,245,0.7);" + ratio = min(1.0, score / (max_score + 1e-12)) + r = 255 + g = int(235 - 90 * ratio) + b = int(220 - 160 * ratio) + alpha = 0.25 + 0.55 * ratio + return f"background-color: rgba({r}, {g}, {b}, {alpha});" + + +def _render_sentence_list(title: str, sentences: Sequence[str], scores: Sequence[float], max_score: float) -> str: + rows: List[str] = [] + for sent, sc in zip(sentences, scores): + style = _color_for_score(abs(float(sc)), max_score) + rows.append( + f'
{sc:.4f}' + f'{escape(sent)}
' + ) + return f""" +
+
{escape(title)}
+ {''.join(rows)} +
+ """ + + +def _render_tokens( + tokens: Sequence[str], + scores: Sequence[float], + max_score: float, + roles: Sequence[str], +) -> str: + spans: List[str] = [] + if max_score <= 0: + max_score = 1e-8 + for idx, tok in enumerate(tokens): + score = float(scores[idx]) if idx < len(scores) else 0.0 + style = _color_for_score(abs(score), max_score) + role = roles[idx] if idx < len(roles) else "gen" + safe_tok = escape(tok) + spans.append( + f'{safe_tok}' + ) + return "".join(spans) + + +def _render_top_table(top_items: List[Dict[str, Any]]) -> str: + if not top_items: + return "
No attribution mass.
" + + header = "
RankIdxScoreSentence
" + body_rows = [] + for rank, item in enumerate(top_items, start=1): + body_rows.append( + f"
{rank}{item['idx']}" + f"{item['score']:.4f}{escape(item['sentence'])}
" + ) + return f"
{header}{''.join(body_rows)}
" + + +def render_case_html( + case_meta: Dict[str, Any], + *, + token_view_raw: Dict[str, Any], + token_view_prompt: Dict[str, Any], + context: Optional[Dict[str, Any]] = None, + hops_sent: Optional[Sequence[Dict[str, Any]]] = None, +) -> str: + has_sentence_view = bool(context) and bool(hops_sent) + prompt_len = len((context or {}).get("prompt_sentences") or []) if has_sentence_view else 0 + gen_len = len((context or {}).get("generation_sentences") or []) if has_sentence_view else 0 + + prompt_max = 0.0 + gen_max = 0.0 + if has_sentence_view: + prompt_max = max( + ( + max(h["sentence_scores_raw"][:prompt_len]) + for h in (hops_sent or []) + if h.get("sentence_scores_raw") and h["sentence_scores_raw"][:prompt_len] + ), + default=0.0, + ) + gen_max = max( + ( + max(h["sentence_scores_raw"][prompt_len:]) + for h in (hops_sent or []) + if h.get("sentence_scores_raw") and h["sentence_scores_raw"][prompt_len:] + ), + default=0.0, + ) + + raw_hops = token_view_raw.get("hops", []) or [] + prompt_hops = token_view_prompt.get("hops", []) or [] + if len(raw_hops) != len(prompt_hops): + raise ValueError( + "token_view_raw and token_view_prompt must have the same number of panels: " + f"raw={len(raw_hops)} prompt={len(prompt_hops)}" + ) + + hop_sections: List[str] = [] + hop_count = len(prompt_hops) + mode = case_meta.get("mode", "ft") + ifr_view = case_meta.get("ifr_view", "aggregate") + sink_span = case_meta.get("sink_span") + panel_titles = case_meta.get("panel_titles") + + def _panel_title(panel_idx: int) -> str: + if isinstance(panel_titles, list) and panel_idx < len(panel_titles): + try: + title = panel_titles[panel_idx] + except Exception: + title = None + if title is not None: + return str(title) + if mode in ("ft", "ft_improve", "ft_split_hop", "ifr_in_all_gen", "ft_attnlrp"): + return f"Hop {panel_idx}" + if mode == "ifr_all_positions_output_only": + return f"IFR output-only panel {panel_idx}" + if mode == "ifr_all_positions": + return f"IFR all-positions panel {panel_idx}" + if mode == "attnlrp": + return "AttnLRP (sink-span aggregate)" + return "IFR (sink-span aggregate)" + + for hop_idx in range(hop_count): + raw_entry = raw_hops[hop_idx] + raw_scores = raw_entry.get("token_scores") or [] + raw_mass = float(raw_entry.get("total_mass", 0.0)) + raw_scale = _robust_abs_max(raw_scores) + if raw_scale <= 0: + raw_scale = float(raw_entry.get("token_score_max") or 0.0) + if raw_scale <= 0: + raw_scale = 1e-8 + + prompt_entry = prompt_hops[hop_idx] + prompt_scores = prompt_entry.get("token_scores") or [] + prompt_mass = float(prompt_entry.get("total_mass", 0.0)) + prompt_scale = _robust_abs_max(prompt_scores) + if prompt_scale <= 0: + prompt_scale = float(prompt_entry.get("token_score_max") or 0.0) + if prompt_scale <= 0: + prompt_scale = 1e-8 + + tok_raw_html = f""" +
+
{escape(token_view_raw.get("label", "Pre-trim token-level heatmap (full)"))}
+
+ {_render_tokens(token_view_raw.get("tokens", []), raw_scores, raw_scale, token_view_raw.get("roles", []))} +
+
+ """ + + tok_prompt_html = f""" +
+
{escape(token_view_prompt.get("label", "Prompt-only token-level heatmap"))}
+
+ {_render_tokens(token_view_prompt.get("tokens", []), prompt_scores, prompt_scale, token_view_prompt.get("roles", []))} +
+
+ """ + + sentence_html = "" + top_html = "" + if has_sentence_view and hop_idx < len(hops_sent or []): + hop = (hops_sent or [])[hop_idx] + raw_scores = hop.get("sentence_scores_raw") or [] + prompt_scores = raw_scores[:prompt_len] + gen_scores = raw_scores[prompt_len:] + # Sentence view is not used by the current case-study runner; keep the path for completeness. + sentence_html = f""" +
+ {_render_sentence_list('Prompt sentences', (context or {}).get('prompt_sentences') or [], prompt_scores, prompt_max)} + {_render_sentence_list('Generation sentences', (context or {}).get('generation_sentences') or [], gen_scores, gen_max)} +
+ """ + top_html = f""" +
+ + {_render_top_table(hop.get('top_sentences') or [])} +
+ """ + + hop_sections.append( + f""" +
+
+
{escape(_panel_title(hop_idx))}
+
+ raw mass: {raw_mass:.6f} | raw scale(p{int(TOKEN_SCALE_QUANTILE*1000)/10:.1f} abs): {raw_scale:.6g} +  |  + prompt mass: {prompt_mass:.6f} | prompt scale(p{int(TOKEN_SCALE_QUANTILE*1000)/10:.1f} abs): {prompt_scale:.6g} +
+
+ {tok_raw_html} + {tok_prompt_html} + {sentence_html} + {top_html} +
+ """ + ) + + thinking_ratios = case_meta.get("thinking_ratios") or [] + ratios_str = ", ".join(f"{r:.4f}" for r in thinking_ratios) if thinking_ratios else "N/A" + + if mode == "ft": + mode_label = "FT Multi-hop (IFR)" + elif mode == "ifr_in_all_gen": + mode_label = "IFR In-all-gen (multi-hop)" + elif mode == "ifr": + mode_label = "IFR Standard" + elif mode == "ifr_all_positions": + mode_label = "IFR All-positions" + elif mode == "ifr_all_positions_output_only": + mode_label = "IFR Output-only (all positions)" + elif mode == "attnlrp": + mode_label = "AttnLRP" + elif mode == "ft_attnlrp": + mode_label = "FT Multi-hop (AttnLRP)" + else: + mode_label = str(mode) + + if mode in ("ft", "ifr_in_all_gen", "ft_attnlrp"): + view_key = "Recursive hops" + view_val = case_meta.get("n_hops") + elif mode in ("ifr", "ifr_all_positions", "ifr_all_positions_output_only"): + view_key = "IFR view" + view_val = ifr_view + elif mode == "attnlrp": + view_key = "AttnLRP view" + view_val = "ft_hop0_span_aggregate" + else: + view_key = "View" + view_val = "N/A" + + scale_row = f"
Token scale: per-panel per-view p{int(TOKEN_SCALE_QUANTILE*1000)/10:.1f}(|score|)
" + neg_handling = case_meta.get("attnlrp_neg_handling") + norm_mode = case_meta.get("attnlrp_norm_mode") + ratio_enabled = case_meta.get("attnlrp_ratio_enabled") + attn_rows = [] + if neg_handling: + attn_rows.append(f"
FT-AttnLRP neg_handling: {escape(str(neg_handling))}
") + if norm_mode: + attn_rows.append(f"
FT-AttnLRP norm_mode: {escape(str(norm_mode))}
") + if ratio_enabled is not None: + attn_rows.append(f"
FT-AttnLRP ratio_enabled: {escape(str(bool(ratio_enabled)))}
") + + header = f""" +
+
+
{escape(mode_label)} Case Study
+
Dataset: {escape(str(case_meta.get('dataset')))} | index: {case_meta.get('index')}
+
+
+
Sink span (gen idx): {escape(str(case_meta.get('sink_span')))}
+
Thinking span (gen idx): {escape(str(case_meta.get('thinking_span')))}
+
Panels: {hop_count}
+
{escape(str(view_key))}: {escape(str(view_val))}
+ {scale_row} + {''.join(attn_rows)} +
Thinking ratios: {ratios_str}
+
+
+ """ + + style = """ + + """ + + title = f"{mode_label} Case Study" + html = f""" + + + + {escape(title)} + {style} + + + {header} + {''.join(hop_sections)} + + """ + return html + + +def _render_sentence_spans(title: str, sentences: Sequence[str], scores: Sequence[float]) -> str: + max_abs = max((abs(float(x)) for x in scores), default=0.0) + spans: List[str] = [] + for idx, sentence in enumerate(sentences): + score = float(scores[idx]) if idx < len(scores) else 0.0 + style = _color_for_score(abs(score), max_abs) + spans.append( + f'{escape(sentence)}' + ) + return f""" +
+
{escape(title)}
+
{''.join(spans)}
+
+ """ + + +def _render_token_spans(title: str, tokens: Sequence[str], scores: Sequence[float]) -> str: + max_abs = max((abs(float(x)) for x in scores), default=0.0) + spans: List[str] = [] + for idx, tok in enumerate(tokens): + score = float(scores[idx]) if idx < len(scores) else 0.0 + style = _color_for_score(abs(score), max_abs) + spans.append( + f'{escape(tok)}' + ) + return f""" +
+
{escape(title)}
+
{''.join(spans)}
+
+ """ + + +def render_mas_sentence_html( + case_meta: Dict[str, Any], + *, + prompt_sentences: Sequence[str], + panels: Sequence[Dict[str, Any]], + generation: Optional[str] = None, +) -> str: + """Render MAS sentence-level diagnostics (attribution / pure ablation / guided marginal).""" + + method_label = case_meta.get("attr_method_label") or case_meta.get("attr_method") or "Unknown method" + title = f"MAS Sentence Study ({method_label})" + + neg_handling = case_meta.get("attnlrp_neg_handling") + norm_mode = case_meta.get("attnlrp_norm_mode") + ratio_enabled = case_meta.get("attnlrp_ratio_enabled") + attn_rows = [] + if neg_handling: + attn_rows.append(f"
FT-AttnLRP neg_handling: {escape(str(neg_handling))}
") + if norm_mode: + attn_rows.append(f"
FT-AttnLRP norm_mode: {escape(str(norm_mode))}
") + if ratio_enabled is not None: + attn_rows.append(f"
FT-AttnLRP ratio_enabled: {escape(str(bool(ratio_enabled)))}
") + + base_score = case_meta.get("base_score") + base_score_row = f"
Base score: {float(base_score):.6f}
" if isinstance(base_score, (int, float)) else "" + + gen_block = "" + if isinstance(generation, str) and generation: + gen_block = f""" +
+
Generation (scored)
+
{escape(generation)}
+
+ """ + + header = f""" +
+
+
{escape(title)}
+
Dataset: {escape(str(case_meta.get('dataset')))} | index: {case_meta.get('index')}
+
+
+
Attribution method: {escape(str(case_meta.get('attr_method')))}
+
Sink span (gen idx): {escape(str(case_meta.get('sink_span')))}
+
Thinking span (gen idx): {escape(str(case_meta.get('thinking_span')))}
+
Panels: {len(panels)}
+ {''.join(attn_rows)} + {base_score_row} +
+
+ """ + + panel_sections: List[str] = [] + for panel in panels: + label = panel.get("variant_label") or panel.get("panel_label") or panel.get("variant") or "Panel" + metrics = panel.get("metrics") or {} + metrics_str = " | ".join( + f"{k}: {float(metrics[k]):.4f}" if isinstance(metrics.get(k), (int, float)) else f"{k}: {metrics.get(k)}" + for k in ("RISE", "MAS", "RISE+AP") + if k in metrics + ) + + attr_weights = panel.get("attr_weights") or [] + pure_deltas = panel.get("pure_sentence_deltas_raw") or [] + guided_deltas = panel.get("guided_sentence_deltas_raw") or panel.get("sentence_deltas_raw") or [] + rank_order = panel.get("sorted_attr_indices") or [] + rank_str = ", ".join(str(int(x)) for x in rank_order) if rank_order else "N/A" + + panel_sections.append( + f""" +
+
+
{escape(str(label))}
+
{escape(metrics_str)}
+
+ + {_render_sentence_spans("Method attribution (sentence weights)", prompt_sentences, attr_weights)} + {_render_sentence_spans("Pure sentence ablation (base โˆ’ score)", prompt_sentences, pure_deltas)} + {_render_sentence_spans("Attribution-guided MAS marginal (path deltas)", prompt_sentences, guided_deltas)} + +
Rank order: {escape(rank_str)}
+
+ """ + ) + + style = """ + + """ + + html = f""" + + + + {escape(title)} + {style} + + + {header} + {gen_block} + {''.join(panel_sections)} + + """ + return html + + +def render_mas_token_html( + case_meta: Dict[str, Any], + *, + prompt_tokens: Sequence[str], + panels: Sequence[Dict[str, Any]], + generation: Optional[str] = None, +) -> str: + """Render MAS token-level diagnostics (attribution weights + guided marginal deltas).""" + + method_label = case_meta.get("attr_method_label") or case_meta.get("attr_method") or "Unknown method" + title = f"MAS Token Study ({method_label})" + + neg_handling = case_meta.get("attnlrp_neg_handling") + norm_mode = case_meta.get("attnlrp_norm_mode") + ratio_enabled = case_meta.get("attnlrp_ratio_enabled") + attn_rows = [] + if neg_handling: + attn_rows.append(f"
FT-AttnLRP neg_handling: {escape(str(neg_handling))}
") + if norm_mode: + attn_rows.append(f"
FT-AttnLRP norm_mode: {escape(str(norm_mode))}
") + if ratio_enabled is not None: + attn_rows.append(f"
FT-AttnLRP ratio_enabled: {escape(str(bool(ratio_enabled)))}
") + + base_score = case_meta.get("base_score") + base_score_row = f"
Base score: {float(base_score):.6f}
" if isinstance(base_score, (int, float)) else "" + + gen_block = "" + if isinstance(generation, str) and generation: + gen_block = f""" +
+
Generation (scored)
+
{escape(generation)}
+
+ """ + + header = f""" +
+
+
{escape(title)}
+
Dataset: {escape(str(case_meta.get('dataset')))} | index: {case_meta.get('index')}
+
+
+
Attribution method: {escape(str(case_meta.get('attr_method')))}
+
Sink span (gen idx): {escape(str(case_meta.get('sink_span')))}
+
Thinking span (gen idx): {escape(str(case_meta.get('thinking_span')))}
+
Prompt tokens: {len(prompt_tokens)}
+
Panels: {len(panels)}
+ {''.join(attn_rows)} + {base_score_row} +
+
+ """ + + panel_sections: List[str] = [] + for panel in panels: + label = panel.get("variant_label") or panel.get("panel_label") or panel.get("variant") or "Panel" + metrics = panel.get("metrics") or {} + metrics_str = " | ".join( + f"{k}: {float(metrics[k]):.4f}" if isinstance(metrics.get(k), (int, float)) else f"{k}: {metrics.get(k)}" + for k in ("RISE", "MAS", "RISE+AP") + if k in metrics + ) + + attr_weights = panel.get("attr_weights") or [] + guided_deltas = panel.get("token_deltas_raw") or [] + rank_order = panel.get("sorted_attr_indices") or [] + rank_str = ", ".join(str(int(x)) for x in rank_order) if rank_order else "N/A" + + panel_sections.append( + f""" +
+
+
{escape(str(label))}
+
{escape(metrics_str)}
+
+ + {_render_token_spans("Method attribution (token weights)", prompt_tokens, attr_weights)} + {_render_token_spans("Attribution-guided MAS marginal (path deltas)", prompt_tokens, guided_deltas)} + +
Rank order: {escape(rank_str)}
+
+ """ + ) + + style = """ + + """ + + html = f""" + + + + {escape(title)} + {style} + + + {header} + {gen_block} + {''.join(panel_sections)} + + """ + return html diff --git a/exp/exp1/README.md b/exp/exp1/README.md new file mode 100644 index 0000000000000000000000000000000000000000..067ab472b08693436aafd683d999396f06b1d8fb --- /dev/null +++ b/exp/exp1/README.md @@ -0,0 +1,46 @@ +# FlashTrace ้•ฟไธŠไธ‹ๆ–‡่€—ๆ—ถๅฎž้ชŒ๏ผˆexp1๏ผ‰ + +่‡ชๅŒ…ๅซ่„šๆœฌ๏ผš`exp/exp1/run_time_curve.py` +็”จ้€”๏ผšๅœจๅ•ไธช RULER ๆ ทๆœฌไธŠ๏ผŒๆต‹้‡ไธๅŒไธŠไธ‹ๆ–‡้•ฟๅบฆไธ‹ๅ„ๅฝ’ๅ› ๆ–นๆณ•็š„ wall-clock ๆ—ถ้—ดไธŽ GPU ๅณฐๅ€ผๆ˜พๅญ˜๏ผŒไพ›่ฎบๆ–‡ไธญ็š„็บฟๆ€งๅขž้•ฟ่กจๆ ผไฝฟ็”จใ€‚ + +## ๆ–นๆณ•่ฆ†็›– +- `IG`๏ผˆ20 ๆญฅ๏ผ‰ +- `attention_I_G`๏ผˆๆณจๆ„ๅŠ› * IG๏ผ‰ +- `attnlrp`๏ผˆๅ•ๆฌกๅไผ ็š„ LRP ็‰ˆๆœฌ๏ผ‰ +- `perturbation_all`๏ผˆlog-loss ablation๏ผ‰ +- `perturbation_CLP`๏ผˆKL ็‰ˆ๏ผ‰ +- `perturbation_REAGENT`๏ผˆMLM ๆ›ฟๆข๏ผŒLED/4096 ไธŠ้™๏ผŒ่ถ…่ฟ‡ๅˆ™ๅฏ่ƒฝๅคฑ่ดฅ๏ผ‰ +- `ifr_all_positions`๏ผˆIFR one-by-one baseline๏ผŒ`sink_chunk_tokens=1` ๅ›บๅฎš๏ผ‰ +- `ifr_multi_hop`๏ผˆFlashTrace๏ผŒๅคš่ทณ+chunk ๆ”ฏๆŒ๏ผ‰ +- `ifr_multi_hop_both`๏ผˆFT-IFR both๏ผšstop_words + in_all_gen๏ผŒๅคš่ทณ+chunk ๆ”ฏๆŒ๏ผ‰ + +## ่ฟ่กŒ็คบไพ‹ +```bash +# ้ป˜่ฎค input ้•ฟๅบฆ 1024,4096,8192๏ผŒoutput ้•ฟๅบฆ 32,256,512๏ผ›ๆฏๆ ผ 3 ๆฌก +python exp/exp1/run_time_curve.py \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 2,3,4,5,6,7 \ + --attr_funcs perturbation_all,perturbation_REAGENT,ifr_all_positions,perturbation_CLP,ifr_multi_hop,ifr_multi_hop_both,attnlrp \ + --input_lengths 10 \ + --output_lengths 2000,5000,10000 \ + --repeats 1 \ + --chunk_tokens 128 \ + --sink_chunk_tokens 32 \ + --catch_oom \ + --ruler_file data/ruler_multihop/8192/vt_h10_c1/validation.jsonl +``` + +่พ“ๅ‡บ๏ผš +- `exp/exp1/out/time_curve_runs.jsonl`๏ผšๆฏๆฌก่ฟ่กŒ็š„ๅŽŸๅง‹่ฎฐๅฝ•๏ผˆattrใ€็›ฎๆ ‡ input/output/totalใ€ๅฎž้™…้•ฟๅบฆใ€timeใ€peak_memใ€status๏ผ‰ใ€‚ +- `exp/exp1/out/time_curve_summary.csv`๏ผšๆŒ‰ๆ–นๆณ• + ็›ฎๆ ‡ input/output ๆฑ‡ๆ€ป็š„ๅ‡ๅ€ผ/ๆ–นๅทฎ๏ผˆๅŒๆ—ถๅ†™ๅ‡บ total=input+output๏ผ‰ใ€‚ + +## ๆณจๆ„ไบ‹้กน +- `--input_lengths` ๆŽงๅˆถ prompt๏ผˆuser prompt๏ผ‰้•ฟๅบฆ๏ผŒ`--output_lengths` ๆŽงๅˆถ output๏ผˆsink๏ผ‰้•ฟๅบฆ๏ผ›ๆฏไธชๆ ผๅญ็š„ total = input + outputใ€‚ +- ๅ…ผๅฎน๏ผšไปๆ”ฏๆŒ `--total_lengths/--lengths`๏ผˆdeprecated๏ผ‰๏ผŒ่กจ็คบ prompt+output ๆ€ป้•ฟๅบฆ๏ผ›prompt ้•ฟๅบฆๆŒ‰ไธค่€…ๅทฎๅ€ผ็”Ÿๆˆใ€‚ +- `--target_text` ไฝœไธบๅŸบๅบ•่ขซ้‡ๅคๆ‹ผๆŽฅไปฅๆปก่ถณ็›ฎๆ ‡ output ้•ฟๅบฆ๏ผŒไป…็”จไบŽๆŽงๅˆถ้•ฟๅบฆ๏ผŒไธๅœจไนŽ่ฏญไน‰ใ€‚ +- `--catch_oom/--no-catch-oom` ็”จไบŽ้€‰ๆ‹ฉๆ˜ฏๆŠŠ OOM ่ฎฐไธบ status ็ปง็ปญ๏ผŒ่ฟ˜ๆ˜ฏ็›ดๆŽฅๆŠ›้”™ไธญๆญขใ€‚ +- ๅคšๅก๏ผš`--cuda 0,1` ไผšๅœจ่„šๆœฌๅฏๅŠจๅ‰่ฎพ็ฝฎ `CUDA_VISIBLE_DEVICES` ๅนถ็”จ `device_map=balanced` ๅˆ†็‰‡ๅŠ ่ฝฝ๏ผ›ๅ•ๅกๆŒ‡ๅฎš `--cuda 0`ใ€‚ +- ่ถ…ๅ‡บๆจกๅž‹ไธŠไธ‹ๆ–‡ (`config.max_position_embeddings`) ไผšๆ ‡่ฎฐ `skipped_model_ctx`๏ผˆๆŒ‰ๅฎž้™…ๅ–‚็ป™ๆจกๅž‹็š„ formatted prompt + output(+eos) token ๆ•ฐๆฃ€ๆŸฅ๏ผ‰ใ€‚ +- `perturbation_REAGENT` ็š„ Longformer ไป…ๆ”ฏๆŒ 4096 tokens๏ผŒ่ถ…่ฟ‡ๅฏ่ƒฝ่ฟ”ๅ›ž OOM ๆˆ– runtime_errorใ€‚ +- IFR multi-hop ๆไพ› `--chunk_tokens/--sink_chunk_tokens` ไปฅๅœจ่ถ…้•ฟไธŠไธ‹ๆ–‡ไธŠๅผบๅˆถๅˆ†ๅ—๏ผŒๆ˜พๅญ˜ไผšไธ‹้™ไฝ†ๆ—ถ้—ด็•ฅๅ‡๏ผ›`ifr_all_positions` ๅˆ†ๆ”ฏๅ›บๅฎš `sink_chunk_tokens=1`ใ€‚ diff --git a/exp/exp1/run_time_curve.py b/exp/exp1/run_time_curve.py new file mode 100644 index 0000000000000000000000000000000000000000..2543b68e4acac3162885eefdde9f6b504ef9b6d1 --- /dev/null +++ b/exp/exp1/run_time_curve.py @@ -0,0 +1,757 @@ +#!/usr/bin/env python3 +""" +Measure wall-clock time and GPU memory for attribution methods across +different context lengths using a single synthetic RULER-style example. + +This script stays self-contained under exp/exp1 and reuses the attribution +implementations in the repo (IG, perturbation, attention*IG, IFR/FlashTrace). +The goal is to populate the time-vs-length table; correctness of the task +content is not important, only matching token lengths and running 3 repeats. +""" + +from __future__ import annotations + +import argparse +import json +import math +import os +import random +import sys +import time +from collections import defaultdict +from pathlib import Path +from typing import Any, Dict, Iterable, List, Optional, Tuple + +import numpy as np + + +def _early_set_cuda_visible_devices() -> None: + """Parse --cuda early to set CUDA_VISIBLE_DEVICES before torch import.""" + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("--cuda", type=str, default=None) + args, _ = parser.parse_known_args(sys.argv[1:]) + if args.cuda and "," in args.cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = args.cuda + + +_early_set_cuda_visible_devices() + +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer + +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + +import llm_attr + +DEFAULT_INPUT_LENGTHS = [1024, 4096, 8192] +DEFAULT_OUTPUT_LENGTHS = [32, 256, 512] +DEFAULT_ATTRS = [ + "IG", + "perturbation_all", + "attention_I_G", + "perturbation_REAGENT", + "ifr_all_positions", + "perturbation_CLP", + "ifr_multi_hop", + "attnlrp", +] +DEFAULT_RULER_FILE = REPO_ROOT / "data" / "ruler_multihop" / "8192" / "vt_h10_c1" / "validation.jsonl" + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser("FlashTrace time/memory curve.") + parser.add_argument("--model", type=str, required=True, help="Model name or HF repo id.") + parser.add_argument("--model_path", type=str, default=None, help="Optional local model path.") + parser.add_argument("--cuda", type=str, default=None, help='CUDA devices, e.g. "0,1" or "0".') + parser.add_argument("--cuda_num", type=int, default=0, help="Single GPU index if --cuda is not set.") + parser.add_argument( + "--attr_funcs", + type=str, + default=",".join(DEFAULT_ATTRS), + help="Comma-separated attribution methods.", + ) + + length_group = parser.add_mutually_exclusive_group() + parser.add_argument( + "--output_lengths", + type=str, + default=",".join(str(x) for x in DEFAULT_OUTPUT_LENGTHS), + help="Comma-separated target output token lengths (sink/output segment).", + ) + length_group.add_argument( + "--input_lengths", + type=str, + default=",".join(str(x) for x in DEFAULT_INPUT_LENGTHS), + help="Comma-separated target input/prompt token lengths (user prompt only; excludes chat template).", + ) + length_group.add_argument( + "--total_lengths", + "--lengths", + dest="total_lengths", + type=str, + default=None, + help="Deprecated. Target total token lengths (prompt + output). Use --input_lengths instead.", + ) + parser.add_argument("--repeats", type=int, default=3, help="Number of runs per cell.") + parser.add_argument("--output_dir", type=str, default="exp/exp1/out", help="Output directory.") + parser.add_argument( + "--ruler_file", + type=str, + default=str(DEFAULT_RULER_FILE), + help="RULER jsonl file providing a long base passage.", + ) + parser.add_argument( + "--chunk_tokens", + type=int, + default=128, + help="IFR chunk_tokens override when context is long.", + ) + parser.add_argument( + "--sink_chunk_tokens", + type=int, + default=32, + help="IFR sink_chunk_tokens override when context is long.", + ) + parser.add_argument( + "--catch_oom", + action=argparse.BooleanOptionalAction, + default=True, + help="If true, treat CUDA OOM as status=oom and continue; if false, let OOM raise.", + ) + parser.add_argument( + "--target_text", + type=str, + default=" The answer is 42.", + help="Base text to tile when constructing outputs of a given length.", + ) + return parser.parse_args() + + +def parse_csv_ints(value: str) -> List[int]: + return [int(x) for x in value.split(",") if x.strip()] + + +def resolve_device(cuda: Optional[str], cuda_num: int) -> str: + if cuda is not None and "," in cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = cuda + return "auto" + if cuda is not None and cuda.strip(): + try: + idx = int(cuda) + except Exception: + idx = 0 + return f"cuda:{idx}" if torch.cuda.is_available() else "cpu" + return f"cuda:{cuda_num}" if torch.cuda.is_available() else "cpu" + + +def load_ruler_base(path: Path, fallback: str) -> str: + if not path.exists(): + return fallback + with path.open() as f: + for line in f: + try: + record = json.loads(line) + if "input" in record: + return record["input"] + except json.JSONDecodeError: + continue + return fallback + + +def build_prompt_to_length(tokenizer, base_text: str, target_tokens: int) -> Tuple[str, int]: + """ + Build a prompt whose tokenized length (without special tokens) is ~target_tokens. + If base_text is shorter, we repeat it; if longer, we truncate. + """ + if target_tokens <= 0: + return "", 0 + + base_ids = tokenizer(base_text, add_special_tokens=False).input_ids + if not base_ids: + base_ids = [tokenizer.eos_token_id] + + tiled: List[int] = [] + while len(tiled) < target_tokens: + tiled.extend(base_ids) + tiled = tiled[:target_tokens] + prompt = tokenizer.decode(tiled, clean_up_tokenization_spaces=False) + return prompt, len(tiled) + + +def build_output_to_length(tokenizer, base_text: str, target_tokens: int) -> Tuple[str, int]: + """ + Build a target/output string of ~target_tokens using a base snippet. + """ + if target_tokens <= 0: + return "", 0 + + base_ids = tokenizer(base_text, add_special_tokens=False).input_ids + if not base_ids: + base_ids = [tokenizer.eos_token_id] + + tiled: List[int] = [] + while len(tiled) < target_tokens: + tiled.extend(base_ids) + tiled = tiled[:target_tokens] + text = tokenizer.decode(tiled, clean_up_tokenization_spaces=False) + return text, len(tiled) + + +def build_formatted_prompt(tokenizer, prompt: str) -> str: + user_prompt = " " + prompt + modified_prompt = llm_attr.DEFAULT_PROMPT_TEMPLATE.format(context=user_prompt, query="") + formatted_prompt = [{"role": "user", "content": modified_prompt}] + return tokenizer.apply_chat_template( + formatted_prompt, + tokenize=False, + add_generation_prompt=True, + enable_thinking=False, + ) + + +def estimate_model_lengths(tokenizer, prompt: str, target: str) -> Dict[str, int]: + user_prompt = " " + prompt + formatted_prompt = build_formatted_prompt(tokenizer, prompt) + + user_prompt_len = len(tokenizer(user_prompt, add_special_tokens=False).input_ids) + formatted_prompt_len = len(tokenizer(formatted_prompt, add_special_tokens=False).input_ids) + generation_len = len(tokenizer(target + tokenizer.eos_token, add_special_tokens=False).input_ids) + + return { + "user_prompt_tokens": user_prompt_len, + "formatted_prompt_tokens": formatted_prompt_len, + "generation_tokens": generation_len, + "total_tokens": formatted_prompt_len + generation_len, + } + + +def exceeds_model_ctx(tokenizer, prompt: str, target: str, max_ctx: Optional[int]) -> bool: + if max_ctx is None: + return False + return estimate_model_lengths(tokenizer, prompt, target)["total_tokens"] > max_ctx + + +def load_model_balanced(model_name: str, device: str): + """Load model with an explicit balanced device_map when multi-GPU is requested.""" + if device == "auto": + model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map="balanced", + torch_dtype=torch.float16, + attn_implementation="eager", + ) + elif isinstance(device, str) and device.startswith("cuda:"): + try: + gpu_idx = int(device.split(":")[1]) + except Exception: + gpu_idx = 0 + model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map={"": gpu_idx}, + torch_dtype=torch.float16, + attn_implementation="eager", + ) + else: + model = AutoModelForCausalLM.from_pretrained( + model_name, + torch_dtype=torch.float16, + attn_implementation="eager", + ) + + tokenizer = AutoTokenizer.from_pretrained(model_name) + tokenizer.pad_token = tokenizer.eos_token + model.eval() + return model, tokenizer + + +def collect_device_indices(device_str: str, model: Any) -> List[int]: + """ + Infer the CUDA device indices that should be tracked for memory stats. + Prefers the model's device map; otherwise falls back to all visible devices + or the single requested device. + """ + if not torch.cuda.is_available(): + return [] + + devices: set[int] = set() + device_map = getattr(model, "hf_device_map", None) + if isinstance(device_map, dict): + for dev in device_map.values(): + if dev is None: + continue + idx: Optional[int] = None + if isinstance(dev, torch.device): + idx = dev.index if dev.index is not None else (0 if dev.type == "cuda" else None) + elif isinstance(dev, str): + try: + d = torch.device(dev) + idx = d.index if d.index is not None else (0 if d.type == "cuda" else None) + except Exception: + idx = None + elif isinstance(dev, int): + idx = dev + if idx is not None: + devices.add(idx) + + if not devices: + if device_str == "auto": + devices.update(range(torch.cuda.device_count())) + elif isinstance(device_str, str) and device_str.startswith("cuda:"): + try: + devices.add(int(device_str.split(":")[1])) + except Exception: + pass + else: + devices.update(range(torch.cuda.device_count())) + + return sorted(devices) + + +def maybe_reset_cuda(device_indices: List[int]) -> None: + if not torch.cuda.is_available() or not device_indices: + return + for idx in device_indices: + try: + torch.cuda.reset_peak_memory_stats(device=idx) + except Exception: + pass + try: + torch.cuda.empty_cache() + except Exception: + pass + + +def measure( + method_fn, + device_indices: List[int], + *, + catch_oom: bool, +) -> Tuple[str, Optional[float], Optional[float], Optional[float], Dict[int, Dict[str, float]]]: + status = "ok" + wall: Optional[float] = None + mem_alloc: Optional[float] = None + mem_reserved: Optional[float] = None + mem_by_device: Dict[int, Dict[str, float]] = {} + try: + if torch.cuda.is_available() and device_indices: + for idx in device_indices: + torch.cuda.synchronize(device=idx) + t0 = time.time() + method_fn() + if torch.cuda.is_available() and device_indices: + for idx in device_indices: + torch.cuda.synchronize(device=idx) + wall = time.time() - t0 + except RuntimeError as e: + if "out of memory" in str(e).lower(): + status = "oom" + if not catch_oom: + raise + else: + status = f"runtime_error: {e}" + if not catch_oom: + raise + except Exception as e: + status = f"error: {e}" + if not catch_oom: + raise + finally: + if torch.cuda.is_available() and device_indices: + try: + total_alloc = 0.0 + total_reserved = 0.0 + for idx in device_indices: + alloc_bytes = torch.cuda.max_memory_allocated(device=idx) + reserved_bytes = torch.cuda.max_memory_reserved(device=idx) + total_alloc += alloc_bytes + total_reserved += reserved_bytes + mem_by_device[idx] = { + "allocated_gb": alloc_bytes / 1e9, + "reserved_gb": reserved_bytes / 1e9, + } + mem_alloc = total_alloc / 1e9 + mem_reserved = total_reserved / 1e9 + except Exception: + pass + return status, wall, mem_alloc, mem_reserved, mem_by_device + + +def make_attr_runner( + attr_func: str, + model: Any, + tokenizer: Any, + chunk_tokens: int, + sink_chunk_tokens: int, + batch_size: int, + prompt: str, + target: str, +): + lf = attr_func.lower() + if lf == "ig": + llm_attributor = llm_attr.LLMGradientAttribtion(model, tokenizer) + + def fn(): + return llm_attributor.calculate_IG_per_generation( + prompt, steps=20, baseline=tokenizer.eos_token_id, batch_size=batch_size, target=target + ) + + return fn + + if lf == "attention_i_g": + llm_attn = llm_attr.LLMAttentionAttribution(model, tokenizer) + llm_ig = llm_attr.LLMGradientAttribtion(model, tokenizer) + + def fn(): + attn = llm_attn.calculate_attention_attribution(prompt, target=target) + ig = llm_ig.calculate_IG_per_generation( + prompt, steps=20, baseline=tokenizer.eos_token_id, batch_size=batch_size, target=target + ) + attn.attribution_matrix = attn.attribution_matrix * ig.attribution_matrix + return attn + + return fn + + if lf == "perturbation_all": + llm_attrtor = llm_attr.LLMPerturbationAttribution(model, tokenizer) + + def fn(): + return llm_attrtor.calculate_feature_ablation_sentences( + prompt, baseline=tokenizer.eos_token_id, measure="log_loss", target=target + ) + + return fn + + if lf == "perturbation_clp": + llm_attrtor = llm_attr.LLMPerturbationAttribution(model, tokenizer) + + def fn(): + return llm_attrtor.calculate_feature_ablation_sentences( + prompt, baseline=tokenizer.eos_token_id, measure="KL", target=target + ) + + return fn + + if lf == "perturbation_reagent": + llm_attrtor = llm_attr.LLMPerturbationAttribution(model, tokenizer) + + def fn(): + return llm_attrtor.calculate_feature_ablation_sentences_mlm(prompt, target=target) + + return fn + + if lf == "ifr_all_positions": + llm_attrtor = llm_attr.LLMIFRAttribution( + model, tokenizer, chunk_tokens=chunk_tokens, sink_chunk_tokens=1 + ) + + def fn(): + return llm_attrtor.calculate_ifr_for_all_positions(prompt, target=target) + + return fn + + if lf == "ifr_multi_hop": + llm_attrtor = llm_attr.LLMIFRAttribution( + model, tokenizer, chunk_tokens=chunk_tokens, sink_chunk_tokens=sink_chunk_tokens + ) + + def fn(): + return llm_attrtor.calculate_ifr_multi_hop(prompt, target=target) + + return fn + + if lf == "ifr_multi_hop_both": + import ft_ifr_improve + + llm_attrtor = ft_ifr_improve.LLMIFRAttributionBoth( + model, tokenizer, chunk_tokens=chunk_tokens, sink_chunk_tokens=sink_chunk_tokens + ) + + def fn(): + return llm_attrtor.calculate_ifr_multi_hop_both(prompt, target=target) + + return fn + + if lf == "attnlrp": + llm_attrtor = llm_attr.LLMLRPAttribution(model, tokenizer) + + def fn(): + return llm_attrtor.calculate_attnlrp(prompt, target=target) + + return fn + + raise ValueError(f"Unsupported attr_func {attr_func}") + + +def compute_batch_size(sequence_length: int, max_input_len: int) -> int: + denom = int(sequence_length) + return max(1, math.floor((max_input_len - 100) / max(1, denom))) + + +def aggregate_results(rows: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + grouped: Dict[Tuple[str, int, int], Dict[str, List[float]]] = defaultdict(lambda: {"time": [], "mem": []}) + statuses: Dict[Tuple[str, int, int], List[str]] = defaultdict(list) + for row in rows: + key = (row["attr_func"], row["target_input_tokens"], row["target_output_tokens"]) + statuses[key].append(row["status"]) + if row.get("time_sec") is not None: + grouped[key]["time"].append(row["time_sec"]) + if row.get("peak_mem_gb") is not None: + grouped[key]["mem"].append(row["peak_mem_gb"]) + + summary = [] + for key, vals in grouped.items(): + attr_func, input_tokens, output_tokens = key + total_tokens = input_tokens + output_tokens + times = vals["time"] + mems = vals["mem"] + summary.append( + { + "attr_func": attr_func, + "target_input_tokens": input_tokens, + "target_total_tokens": total_tokens, + "target_output_tokens": output_tokens, + "time_mean": np.mean(times) if times else None, + "time_std": np.std(times) if times else None, + "mem_mean": np.mean(mems) if mems else None, + "mem_std": np.std(mems) if mems else None, + "statuses": statuses[key], + } + ) + return summary + + +def append_jsonl_row(f, row: Dict[str, Any]) -> None: + f.write(json.dumps(row) + "\n") + f.flush() + try: + os.fsync(f.fileno()) + except OSError: + pass + + +def write_summary_csv(rows: List[Dict[str, Any]], out_dir: Path) -> Path: + summary = aggregate_results(rows) + summary_path = out_dir / "time_curve_summary.csv" + tmp_path = out_dir / "time_curve_summary.csv.tmp" + + with tmp_path.open("w") as f: + f.write( + "attr_func,target_input_tokens,target_output_tokens,target_total_tokens,time_mean,time_std,peak_mem_mean,peak_mem_std,statuses\n" + ) + for row in summary: + f.write( + "{},{},{},{},{},{},{},{},{}\n".format( + row["attr_func"], + row["target_input_tokens"], + row["target_output_tokens"], + row["target_total_tokens"], + "" if row["time_mean"] is None else f"{row['time_mean']:.4f}", + "" if row["time_std"] is None else f"{row['time_std']:.4f}", + "" if row["mem_mean"] is None else f"{row['mem_mean']:.4f}", + "" if row["mem_std"] is None else f"{row['mem_std']:.4f}", + "|".join(row["statuses"]), + ) + ) + f.flush() + try: + os.fsync(f.fileno()) + except OSError: + pass + + tmp_path.replace(summary_path) + return summary_path + + +def main() -> None: + args = parse_args() + device = resolve_device(args.cuda, args.cuda_num) + attr_funcs = [a.strip() for a in args.attr_funcs.split(",") if a.strip()] + target_output_lengths = parse_csv_ints(args.output_lengths) + out_dir = Path(args.output_dir) + out_dir.mkdir(parents=True, exist_ok=True) + + random.seed(42) + np.random.seed(42) + torch.manual_seed(42) + + model_name = args.model if args.model_path is None else args.model_path + model, tokenizer = load_model_balanced(model_name, device) + device_indices = collect_device_indices(device, model) + max_ctx = getattr(getattr(model, "config", None), "max_position_embeddings", None) + + base_text = load_ruler_base(Path(args.ruler_file), fallback="RULER fallback text. ") + target_base = args.target_text + all_rows: List[Dict[str, Any]] = [] + runner = None + raised: Optional[BaseException] = None + jsonl_f = None + jsonl_path = out_dir / "time_curve_runs.jsonl" + summary_path = out_dir / "time_curve_summary.csv" + + def record_row(row: Dict[str, Any]) -> None: + all_rows.append(row) + if jsonl_f is not None: + append_jsonl_row(jsonl_f, row) + write_summary_csv(all_rows, out_dir) + + using_deprecated_total = args.total_lengths is not None + if using_deprecated_total: + target_total_lengths = parse_csv_ints(args.total_lengths) + length_grid: List[Tuple[int, int, int]] = [] + for total_tokens in target_total_lengths: + for output_tokens in target_output_lengths: + length_grid.append((total_tokens - output_tokens, output_tokens, total_tokens)) + else: + target_input_lengths = parse_csv_ints(args.input_lengths) + length_grid = [] + for input_tokens in target_input_lengths: + for output_tokens in target_output_lengths: + length_grid.append((input_tokens, output_tokens, input_tokens + output_tokens)) + + try: + jsonl_f = jsonl_path.open("w") + write_summary_csv([], out_dir) + + for input_tokens, output_tokens, total_tokens in length_grid: + if input_tokens <= 0: + for attr in attr_funcs: + for rep in range(args.repeats): + record_row( + { + "attr_func": attr, + "target_input_tokens": input_tokens, + "target_output_tokens": output_tokens, + "target_total_tokens": total_tokens, + "actual_input_tokens": None, + "actual_output_tokens": None, + "actual_total_tokens_raw": None, + "actual_user_prompt_tokens": None, + "actual_formatted_prompt_tokens": None, + "actual_generation_tokens": None, + "actual_total_tokens": None, + "status": "skipped_nonpositive_input", + "time_sec": None, + "peak_mem_gb": None, + "peak_mem_reserved_gb": None, + "repeat": rep, + "used_deprecated_total_lengths": using_deprecated_total, + } + ) + continue + + prompt, actual_input_len = build_prompt_to_length(tokenizer, base_text, input_tokens) + target, actual_output_len = build_output_to_length(tokenizer, target_base, output_tokens) + actual_total_tokens_raw = len(tokenizer(prompt + target, add_special_tokens=False).input_ids) + model_lens = estimate_model_lengths(tokenizer, prompt, target) + + if max_ctx is not None and model_lens["total_tokens"] > max_ctx: + for attr in attr_funcs: + for rep in range(args.repeats): + record_row( + { + "attr_func": attr, + "target_input_tokens": input_tokens, + "target_output_tokens": output_tokens, + "target_total_tokens": total_tokens, + "actual_input_tokens": actual_input_len, + "actual_output_tokens": actual_output_len, + "actual_total_tokens_raw": actual_total_tokens_raw, + "actual_user_prompt_tokens": model_lens["user_prompt_tokens"], + "actual_formatted_prompt_tokens": model_lens["formatted_prompt_tokens"], + "actual_generation_tokens": model_lens["generation_tokens"], + "actual_total_tokens": model_lens["total_tokens"], + "status": "skipped_model_ctx", + "time_sec": None, + "peak_mem_gb": None, + "peak_mem_reserved_gb": None, + "repeat": rep, + "used_deprecated_total_lengths": using_deprecated_total, + } + ) + continue + + batch_size = compute_batch_size(model_lens["total_tokens"], max_input_len=max_ctx or 200000) + + for attr in attr_funcs: + for rep in range(args.repeats): + runner = None + maybe_reset_cuda(device_indices) + try: + runner = make_attr_runner( + attr, + model=model, + tokenizer=tokenizer, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + batch_size=batch_size, + prompt=prompt, + target=target, + ) + except RuntimeError as e: + if "out of memory" in str(e).lower(): + status = "oom" + if not args.catch_oom: + raise + else: + status = f"init_runtime_error: {e}" + if not args.catch_oom: + raise + wall = None + mem_alloc = None + mem_reserved = None + mem_by_device = {} + except Exception as e: + status = f"init_error: {e}" + if not args.catch_oom: + raise + wall = None + mem_alloc = None + mem_reserved = None + mem_by_device = {} + else: + status, wall, mem_alloc, mem_reserved, mem_by_device = measure( + runner, device_indices=device_indices, catch_oom=args.catch_oom + ) + finally: + runner = None + + record_row( + { + "attr_func": attr, + "target_input_tokens": input_tokens, + "target_output_tokens": output_tokens, + "target_total_tokens": total_tokens, + "actual_input_tokens": actual_input_len, + "actual_output_tokens": actual_output_len, + "actual_total_tokens_raw": actual_total_tokens_raw, + "actual_user_prompt_tokens": model_lens["user_prompt_tokens"], + "actual_formatted_prompt_tokens": model_lens["formatted_prompt_tokens"], + "actual_generation_tokens": model_lens["generation_tokens"], + "actual_total_tokens": model_lens["total_tokens"], + "status": status, + "time_sec": wall, + "peak_mem_gb": mem_reserved if mem_reserved is not None else mem_alloc, + "peak_mem_reserved_gb": mem_reserved, + "peak_mem_by_device_gb": mem_by_device if mem_by_device else None, + "repeat": rep, + "used_deprecated_total_lengths": using_deprecated_total, + } + ) + except BaseException as e: + raised = e + finally: + runner = None + if jsonl_f is not None: + jsonl_f.close() + write_summary_csv(all_rows, out_dir) + print(f"Wrote per-run records to {jsonl_path}") + print(f"Wrote summary to {summary_path}") + + if raised is not None: + raise raised + + +if __name__ == "__main__": + main() diff --git a/exp/exp2/DATASETS.md b/exp/exp2/DATASETS.md new file mode 100644 index 0000000000000000000000000000000000000000..673b05b30ddb4d2a7aff868749a17722c06d8499 --- /dev/null +++ b/exp/exp2/DATASETS.md @@ -0,0 +1,231 @@ +# exp/exp2 ๆ•ฐๆฎ้›†ไธŽๆ ทๆœฌๆต่ฏดๆ˜Ž + +ๆœฌๆ–‡ไปถ่ฏดๆ˜Ž Experiment 2 ไธญๆ”ฏๆŒ็š„ๆ•ฐๆฎ้›†ใ€ๆ ทๆœฌ็ป“ๆž„๏ผŒไปฅๅŠๅœจใ€Œ้‡‡ๆ ท้˜ถๆฎตใ€ไธŽใ€Œๅฝ’ๅ› ้˜ถๆฎตใ€็š„ๅค„็†ๆ–นๅผใ€‚ + +## ๆ”ฏๆŒ็š„ๆ•ฐๆฎ้›† +- `morehopqa`๏ผˆ`data/with_human_verification.json`๏ผ‰ +- RULER ็ณปๅˆ— JSONL๏ผš`hotpotqa_long`ใ€`niah_*`ใ€`vt_*`๏ผˆ่‡ชๅŠจๅœจ `data/ruler_multihop//.../validation.jsonl` ๆœ็ดข๏ผ‰๏ผŒๆˆ–็›ดๆŽฅไผ ๅ…ฅไปปๆ„ RULER JSONL ่ทฏๅพ„ +- ๅ…ถไฝ™ๆ•ฐๆฎ้›†๏ผˆๅฆ‚ math๏ผ‰่ขซๆ˜พๅผ่ทณ่ฟ‡ +- ๅฝ’ๅ› ้˜ถๆฎตๅŒๆ ทไผ˜ๅ…ˆไฝฟ็”จ็ผ“ๅญ˜ๆ–‡ไปถ `exp/exp2/data/.jsonl`๏ผŒๅฆๅˆ™ๆŒ‰ไธŠ่ฟฐ่ง„ๅˆ™่งฃๆž๏ผ›ไผ ๅ…ฅๅญ˜ๅœจ็š„ JSONL ่ทฏๅพ„ไนŸไผšๆŒ‰ RULER ็ป“ๆž„ๅŠ ่ฝฝ + +### ๅ…ฑๅŒ็š„ๆ ทๆœฌๅญ—ๆฎตๅฎšไน‰ +```json +{ + "prompt": "<ไธŠไธ‹ๆ–‡+้—ฎ้ข˜>", + "target": "<็ญ”ๆกˆๆˆ–็”Ÿๆˆ>", + "indices_to_explain": [start_tok, end_tok] | null, // token-level๏ผš้œ€่ฆ่งฃ้‡Š็š„ generation token span๏ผˆ้—ญๅŒบ้—ด๏ผ‰ + "attr_mask_indices": [...], // legacy๏ผš่ฆ†็›–็އ้‡‘ๆ ‡ๅฅๅญ็ดขๅผ•๏ผˆๅฝ“ๅ‰ exp2 ไธๅ†ไฝฟ็”จ๏ผ‰๏ผŒๅฏ่ƒฝไธบ null + "sink_span": [start, end] | null, // ็”Ÿๆˆ token ไธญ็š„็ญ”ๆกˆ็‰‡ๆฎต + "thinking_span": [start, end] | null, // ็”Ÿๆˆ token ไธญ็š„ CoT ็‰‡ๆฎต + "metadata": { ... } // ๆ•ฐๆฎ้›†็‰นๅฎšๅ…ƒไฟกๆฏ +} +``` +- **`CachedExample`**๏ผš`dataset_utils.py` ็ปŸไธ€็š„ๅ†…ๅญ˜ๆ€็ป“ๆž„๏ผŒๅญ—ๆฎตไธŽไธŠ่ฟฐ JSON ๅฎŒๅ…จไธ€่‡ด๏ผŒ็”จไบŽ้‡‡ๆ ท้˜ถๆฎต๏ผˆๅŠ ่ฝฝๅŽŸๅง‹ๆ•ฐๆฎ๏ผ‰ไธŽๅฝ’ๅ› ้˜ถๆฎต๏ผˆๅŠ ่ฝฝ็ผ“ๅญ˜ๆˆ–ๅŽŸๅง‹๏ผ‰ใ€‚ +- **็ผ“ๅญ˜่กŒ๏ผˆJSONL๏ผ‰**๏ผš`sample_and_filter.py` ๅ†™ๅ…ฅ็š„ๆฏ่กŒ JSON๏ผŒไธŽ `CachedExample` ๅญ—ๆฎตไธ€ไธ€ๅฏนๅบ”ใ€‚ +- **้‡‡ๆ ท้˜ถๆฎตๅค„็†ๆต๏ผˆ้€š็”จ๏ผ‰**๏ผš + 1. ๅŠ ่ฝฝๅŽŸๅง‹ๆ•ฐๆฎ้›†ๆ ทๆœฌ๏ผˆ`prompt`/`indices_to_explain` ็ญ‰ไฟๆŒไธ€่‡ด๏ผ‰ใ€‚ + 2. ๆŒ‰ๆจกๆฟ่ฐƒ็”จ็”Ÿๆˆๆจกๅž‹๏ผŒ่ฆๆฑ‚ใ€Œๆ€่€ƒๆ–‡ๆœฌ + ๆœซๅฐพ \\box{} ็ญ”ๆกˆใ€ใ€‚ + 3. ่‹ฅ็”Ÿๆˆไธ็ฌฆๅˆใ€Œๆ€่€ƒ + ๅ•ไธช \\box{} ไธ”ๆ— ๅฐพๅทดใ€็š„ๆ ผๅผ๏ผŒ็›ดๆŽฅไธขๅผƒ่ฏฅๆ ทๆœฌใ€‚ + 4. ๆๅ–ๆ€่€ƒ็‰‡ๆฎตไธŽ `\\box{}` ๅ†…ๆ–‡ๆœฌ๏ผŒไป…็”จ `\\box{}` ๅ†…ๆ–‡่ฐƒ็”จๅˆคๅฎšๆจกๅž‹ใ€‚ + 5. ๅˆคๅฎšไธบ True ๆ—ถ๏ผŒ้‡ๆ–ฐๆ‹ผๆŽฅใ€Œๆ€่€ƒ็‰‡ๆฎต + ๅŽป้™ค box ๅŒ…่ฃน็š„็ญ”ๆกˆๆ–‡ๆœฌใ€ไฝœไธบ `target`๏ผŒๅนถๆฎๆญค่ฎฐๅฝ• `sink_span`/`thinking_span`ใ€‚ + 6. ๅ†™ๅ…ฅ็ผ“ๅญ˜๏ผšๅชไฟ็•™ `reference_answer`ใ€`judge_response`๏ผˆๅฏ้€‰ `boxed_answer`๏ผ‰๏ผŒไธๅ†ๅญ˜ๅ‚จ `candidate_answer`ใ€‚ + +### ็”Ÿๆˆๅˆ‡ๅˆ†ไธŽ span ่งฃๆž +- `split_boxed_generation`๏ผˆ`dataset_utils.py`๏ผ‰ๆ ก้ชŒๆ ผๅผ๏ผšๅฟ…้กปๆ˜ฏใ€Œ้ž็ฉบๆ€่€ƒๆ–‡ๆœฌ + ๅ•ไธชๆœซๅฐพ \\box{}ใ€ไธ”็ฎฑไฝ“ไน‹ๅŽๆ— ๅ…ถไป–ๅญ—็ฌฆ๏ผŒๅฆๅˆ™็›ดๆŽฅ่ทณ่ฟ‡ใ€‚ +- `target` ็”ฑใ€Œๆ€่€ƒ็‰‡ๆฎต + ๆข่กŒ + ๆœ€็ปˆ็ญ”ๆกˆๆ–‡ๆœฌ๏ผˆๆ—  box๏ผ‰ใ€้‡็ป„ใ€‚ +- `attach_spans_from_answer` ไฝฟ็”จ tokenizer ็š„ offset mapping ๅฐ†ๆœ€็ปˆ็ญ”ๆกˆๅœจ `target` ไธญ็š„ๅญ—็ฌฆๅŒบ้—ดๆ˜ ๅฐ„ๅˆฐ token ็บง็ดขๅผ•๏ผŒๅพ—ๅˆฐ `sink_span`๏ผ›`thinking_span` ๅ–ไปŽๅผ€ๅคดๅˆฐ `sink_span` ๅ‰ไธ€ token ็š„้—ญๅŒบ้—ดใ€‚ไธค่€…ๅ‡ไธบ token ็บง span๏ผŒๆปก่ถณๅŽ็ปญๅคš่ทณ IFR ็š„่ฐƒ็”จ็บฆๅฎšใ€‚ +- `indices_to_explain` ๅœจ้‡‡ๆ ทๅ†™็ผ“ๅญ˜ๆ—ถ็ปŸไธ€่ฎพ็ฝฎไธบ `sink_span`๏ผˆboxed ๅ†…ๆ–‡ๅœจ `target` ไธญๅฏนๅบ”็š„ generation token span๏ผ‰ใ€‚ + +--- + +## MoreHopQA +- **ๅŽŸๅง‹ๆ ทๆœฌ็ป“ๆž„๏ผˆ`MoreHopQAAttributionDataset` โ†’ `CachedExample`๏ผ‰** + ```json + { + "prompt": "\\n", + "target": null, + "indices_to_explain": null, + "attr_mask_indices": null, + "sink_span": null, + "thinking_span": null, + "metadata": { + "answer": "", + "_id": "", + "original_context": <ๅŽŸๅง‹ไธŠไธ‹ๆ–‡็ป“ๆž„> + } + } + ``` + - ๅŠ ่ฝฝๆ—ถๆœบ๏ผš`DatasetLoader.load_raw("morehopqa")` ๅœจ้‡‡ๆ ท้˜ถๆฎตใ€ๅฝ’ๅ› ้˜ถๆฎต๏ผˆๆ— ็ผ“ๅญ˜ๆ—ถ๏ผ‰้ƒฝไผšไบงๅ‡บ `CachedExample`ใ€‚ + - ่ฏดๆ˜Ž๏ผšexp2 ็š„ token-level row/rec ้œ€่ฆ `target` + ๅฏๅฎšไฝ็š„็ญ”ๆกˆ token span๏ผ›ๅปบ่ฎฎๅ…ˆ่ท‘ `sample_and_filter.py` ไบงๅ‡บ็ผ“ๅญ˜ๅŽๅ†ๅšๅฝ’ๅ› ่ฏ„ไผฐใ€‚ + +- **้‡‡ๆ ท้˜ถๆฎต๏ผˆ็”Ÿๆˆ & ่ฟ‡ๆปคๅŽๅ†™็ผ“ๅญ˜๏ผ‰** + ```json + { + "prompt": "<ๅŒไธŠ>", + "target": "<็”Ÿๆˆ็š„ CoT + ๆœ€็ปˆ็ญ”ๆกˆๆ–‡ๆœฌ๏ผˆๅทฒๅŽปๆމ box ๅŒ…่ฃน๏ผ‰>", + "indices_to_explain": [start_tok, end_tok], + "attr_mask_indices": null, + "sink_span": [start_tok, end_tok] | null, + "thinking_span": [start_tok, end_tok] | null, + "metadata": { + "answer": "", + "_id": "", + "original_context": <ๅŽŸๅง‹ไธŠไธ‹ๆ–‡็ป“ๆž„>, + "reference_answer": "", + "judge_response": "", + "boxed_answer": "<ๅฏ้€‰๏ผŒboxed ่งฃๆž็ป“ๆžœ>" + } + } + ``` + - `sink_span`/`thinking_span`๏ผšไป…ๅœจๆˆๅŠŸ่งฃๆž `\\box{}` ๆ—ถๅกซๅ……๏ผ›`target` ไธบใ€Œๆ€่€ƒ + ๆœ€็ปˆ็ญ”ๆกˆๆ–‡ๆœฌใ€็š„่ฃๅ‰ช็‰ˆใ€‚ + - ๅ†™ๅ…ฅ๏ผš`exp/exp2/data/morehopqa.jsonl`ใ€‚ + +- **ๅฝ’ๅ› ้˜ถๆฎต๏ผˆๅŠ ่ฝฝ็ผ“ๅญ˜ไผ˜ๅ…ˆ๏ผ‰** + - ๅŠ ่ฝฝ๏ผš`run_exp.py` ไผ˜ๅ…ˆ `load_cached`๏ผˆJSONL โ†’ `CachedExample`๏ผ‰๏ผŒๅฆๅˆ™ๅ›ž้€€ๅŽŸๅง‹็ป“ๆž„ๅนถๅœจ็บฟ็”Ÿๆˆ `target`ใ€‚ + - ไฝฟ็”จ๏ผšๅฟ ๅฎžๅบฆ๏ผˆtoken-level RISE/MAS๏ผ‰็›ดๆŽฅ็”จ็ผ“ๅญ˜็š„ `target`๏ผ›`ifr_multi_hop` ๅœจๆœ‰ `sink_span`/`thinking_span` ๆ—ถ้™ๅฎš็ญ”ๆกˆ/CoT๏ผŒๅฆๅˆ™่ง†ๆ•ดไธช็”Ÿๆˆไธบ sinkใ€‚ + +--- + +## RULER ็ƒญ็‚น้—ฎ็ญ”๏ผˆ`hotpotqa_long`๏ผ‰ +- **ๅŽŸๅง‹ๆ ทๆœฌ็ป“ๆž„๏ผˆ`RulerAttributionDataset` โ†’ `CachedExample`๏ผ‰** + ```json + { + "prompt": " + ", + "target": "", + "indices_to_explain": [0], + "attr_mask_indices": [<ๅฅๅญ็ดขๅผ•>...] | null, + "sink_span": null, + "thinking_span": null, + "metadata": { + "dataset": "ruler", + "length": , + "length_w_model_temp": , + "outputs": [...], + "answer_prefix": "", + "token_position_answer": , + "needle_spans": [ + { + "title": "", + "doc_index": , + "document_number": , + "sentence_index": , + "sentence": "", + "context_span": [start, end], + "span": [start, end], + "snippet": "" + }, + ... + ], + "prompt_sentence_count": , + "reference_answer": "<ๅœจ loader ไธญ่กฅๅ……๏ผŒๆฅ่‡ช outputs ๆˆ– target>" + } + } + ``` + - ๅŠ ่ฝฝๆ—ถๆœบ๏ผš`DatasetLoader.load_raw("hotpotqa_long")` ๅœจ้‡‡ๆ ท้˜ถๆฎตใ€ๅฝ’ๅ› ้˜ถๆฎต๏ผˆๆ— ็ผ“ๅญ˜ๆ—ถ๏ผ‰้ƒฝไผšไบงๅ‡บ `CachedExample`ใ€‚ + +- **้‡‡ๆ ท้˜ถๆฎต๏ผˆ็”Ÿๆˆ & ่ฟ‡ๆปคๅŽๅ†™็ผ“ๅญ˜๏ผ‰** + ```json + { + "prompt": "<ๅŒไธŠ>", + "target": "<็”Ÿๆˆ็š„ CoT + ๆœ€็ปˆ็ญ”ๆกˆๆ–‡ๆœฌ๏ผˆๅทฒๅŽปๆމ box ๅŒ…่ฃน๏ผ‰>", + "indices_to_explain": [-2], + "attr_mask_indices": [<ๅฅๅญ็ดขๅผ•>...] | null, + "sink_span": [start_tok, end_tok] | null, + "thinking_span": [start_tok, end_tok] | null, + "metadata": { + "dataset": "ruler", + "length": , + "length_w_model_temp": , + "outputs": [...], + "answer_prefix": "", + "token_position_answer": , + "needle_spans": [...], + "prompt_sentence_count": , + "reference_answer": "", + "judge_response": "", + "boxed_answer": "<ๅฏ้€‰>" + } + } + ``` + - `attr_mask_indices` ไฟ็•™ๅŽŸๅ€ผ๏ผ›`indices_to_explain` ็ปŸไธ€ไธบๆœซๅฅ `[-2]`๏ผˆๆœ€ๅŽไธ€ไธช้ž EOS ็”Ÿๆˆๅฅ๏ผ‰๏ผ›`sink_span`/`thinking_span` ไป…ๅœจๆˆๅŠŸ่งฃๆž `\\box{}` ๆ—ถๅกซๅ……๏ผ›`target` ไธบใ€Œๆ€่€ƒ + ๆœ€็ปˆ็ญ”ๆกˆๆ–‡ๆœฌใ€็š„่ฃๅ‰ช็‰ˆใ€‚ + - ๅ†™ๅ…ฅ๏ผš`exp/exp2/data/hotpotqa_long.jsonl`ใ€‚ + +- **ๅฝ’ๅ› ้˜ถๆฎต๏ผˆๅŠ ่ฝฝ็ผ“ๅญ˜ไผ˜ๅ…ˆ๏ผ‰** + - ๅŠ ่ฝฝ๏ผšไผ˜ๅ…ˆ `load_cached`๏ผˆJSONL โ†’ `CachedExample`๏ผ‰๏ผŒๅฆๅˆ™ๅ›ž้€€ๅŽŸๅง‹่งฃๆžใ€‚ + - ไฝฟ็”จ๏ผš่ฆ†็›–็އไฝฟ็”จ `attr_mask_indices`๏ผ›ๅฟ ๅฎžๅบฆไธŽ `ifr_multi_hop` ๅˆฉ็”จ็ผ“ๅญ˜็š„ `sink_span`/`thinking_span` ๅฎšไฝ็ญ”ๆกˆ/CoT๏ผŒ่‹ฅ็ผบๅคฑๅˆ™่ง†ๆ•ดไธช็”Ÿๆˆไธบ sinkใ€‚ + +--- + +## RULER NIAH / Variable Tracking๏ผˆ`niah_*`, `vt_*`๏ผ‰ +- **ๅŽŸๅง‹ๆ ทๆœฌ็ป“ๆž„๏ผˆๅŒ RULER ้€š็”จ๏ผ‰** + ```json + { + "prompt": " + ", + "target": "", + "indices_to_explain": [0], + "attr_mask_indices": [<ๅฅๅญ็ดขๅผ•>...] | null, + "sink_span": null, + "thinking_span": null, + "metadata": { + "dataset": "ruler", + "length": , + "length_w_model_temp": , + "outputs": [...], + "answer_prefix": "", + "token_position_answer": , + "needle_spans": [...], + "prompt_sentence_count": , + "reference_answer": "<ๅœจ loader ไธญ่กฅๅ……>" + } + } + ``` + - ๅŠ ่ฝฝๆ—ถๆœบ๏ผš`DatasetLoader.load_raw("")` ๅœจ้‡‡ๆ ท้˜ถๆฎตใ€ๅฝ’ๅ› ้˜ถๆฎต๏ผˆๆ— ็ผ“ๅญ˜ๆ—ถ๏ผ‰ไฝฟ็”จใ€‚ + +- **้‡‡ๆ ท้˜ถๆฎต๏ผˆ็”Ÿๆˆ & ่ฟ‡ๆปคๅŽๅ†™็ผ“ๅญ˜๏ผ‰** + ```json + { + "prompt": "<ๅŒไธŠ>", + "target": "<ๆ€่€ƒ + ๆœ€็ปˆ็ญ”ๆกˆๆ–‡ๆœฌ๏ผˆๆ—  box๏ผ‰๏ผŒๆ— ๅ…ถไป–ๅฐพๅทด>", + "indices_to_explain": [start_tok, end_tok], + "attr_mask_indices": [<ๅฅๅญ็ดขๅผ•>...] | null, + "sink_span": [start_tok, end_tok] | null, + "thinking_span": [start_tok, end_tok] | null, + "metadata": { + "dataset": "ruler", + "length": , + "length_w_model_temp": , + "outputs": [...], + "answer_prefix": "", + "token_position_answer": , + "needle_spans": [...], + "prompt_sentence_count": , + "reference_answer": "", + "judge_response": "", + "boxed_answer": "<ๅฏ้€‰>" + } + } + ``` + - ็”Ÿๆˆ/ๅˆคๅฎšๆต็จ‹ไธŽ `hotpotqa_long` ็›ธๅŒ๏ผ›`target` ๆ˜ฏ่ฃๅ‰ชๅŽ็š„ใ€Œๆ€่€ƒ + ๆœ€็ปˆ็ญ”ๆกˆๆ–‡ๆœฌใ€ใ€‚ + - ๅ†™ๅ…ฅ๏ผš`exp/exp2/data/.jsonl`๏ผˆไพ‹ๅฆ‚ `niah_mq_q2.jsonl`, `vt_h6_c1.jsonl`๏ผ‰ใ€‚ + +- **ๅฝ’ๅ› ้˜ถๆฎต๏ผˆๅŠ ่ฝฝ็ผ“ๅญ˜ไผ˜ๅ…ˆ๏ผ‰** + - ไธŽ `hotpotqa_long` ็›ธๅŒ๏ผšไผ˜ๅ…ˆ็ผ“ๅญ˜๏ผŒๅฆๅˆ™ๅŽŸๅง‹๏ผ›ๆขๅค็އ๏ผˆ`recovery_ruler`๏ผ‰ไฝฟ็”จ `metadata.needle_spans`๏ผˆๆ˜ ๅฐ„ๅˆฐ prompt tokens๏ผ‰๏ผ›ๅคš่ทณ IFR ๅœจๆœ‰ `sink_span`/`thinking_span` ๆ—ถไฝœ็”จไบŽ็ญ”ๆกˆ/CoTใ€‚ + +--- + +## `indices_to_explain` ็บฆๅฎš +- token-level๏ผš`indices_to_explain = [start_tok, end_tok]`๏ผˆ้—ญๅŒบ้—ด๏ผ‰๏ผŒๅๆ ‡็ณปไธบ `tokenizer(target, add_special_tokens=False)` ็š„ generation token indicesใ€‚ +- exp2 ๆŽจ่๏ผš`indices_to_explain == sink_span`๏ผŒๅณ boxed ๅ†…ๆ–‡๏ผˆๆœ€็ปˆ็ญ”ๆกˆ๏ผ‰ๅœจ `target` ไธญๅฏนๅบ”็š„ token spanใ€‚ + +--- + +## ่‡ชๅฎšไน‰ RULER JSONL ่ทฏๅพ„ +- ่‹ฅ `--dataset` ไผ ๅ…ฅๅญ˜ๅœจ็š„ JSONL ่ทฏๅพ„๏ผŒ`dataset_from_name` ๆŒ‰ RULER ๆ–‡ไปถ่งฃๆž๏ผŒๅญ—ๆฎตไธŽๆต็จ‹ๅŒ RULER ็ณปๅˆ—ใ€‚ +- ้‡‡ๆ ทใ€ๅฝ’ๅ› ้˜ถๆฎต่กŒไธบไธŽไธŠๆ–‡ RULER ๆ่ฟฐไธ€่‡ด๏ผŒๅชๆ˜ฏๆ–‡ไปถๅ็”ฑๆ˜พๅผ่ทฏๅพ„ๅ†ณๅฎšใ€‚ + +--- + +## ๅฝ’ๅ› ้˜ถๆฎตๅŠ ่ฝฝไผ˜ๅ…ˆ็บงไธŽๆ•ˆๆžœ +- `run_exp.py` ๅŠ ่ฝฝ้กบๅบ๏ผš`exp/exp2/data/.jsonl` ็ผ“ๅญ˜ > ๆ˜พๅผ็ป™ๅฎš็š„ JSONL ่ทฏๅพ„ > ๅŽŸๅง‹่งฃๆž๏ผˆMoreHopQA ๆˆ– RULER๏ผ‰ +- ๆขๅค็އ (`mode=recovery_ruler`) ไป…ๆ”ฏๆŒ RULER๏ผˆ่ฆๆฑ‚ `metadata.needle_spans`๏ผ‰๏ผŒๅฆๅˆ™ๆ‹’็ป +- ๅฟ ๅฎžๅบฆ (`mode=faithfulness_gen`) ไฝฟ็”จ็”Ÿๆˆๆ–‡ๆœฌ๏ผ›`ifr_multi_hop` ๅœจๆœ‰ `sink_span`/`thinking_span` ๆ—ถๆ‰ๅฏน็ญ”ๆกˆ/CoT ๅšๅคš่ทณ๏ผŒๅฆๅˆ™้€€ๅŒ–ไธบๆ•ดๆฎต็”Ÿๆˆ diff --git a/exp/exp2/README.md b/exp/exp2/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e79945839761315fefb72c17f97b156b29e1d5e6 --- /dev/null +++ b/exp/exp2/README.md @@ -0,0 +1,106 @@ +# FlashTrace ๅฎž้ชŒ 2๏ผˆๅคšๆญฅๆŽจ็†ไธ‹็š„ๅฟ ๅฎžๅบฆ๏ผ‰ + +ๆœฌ็›ฎๅฝ•ๆไพ›ใ€Œ11 ๆ•ฐๆฎ้›† ร— 9 ๆ–นๆณ• ร— 3 ๆŒ‡ๆ ‡ใ€็š„ๅฎž้ชŒๅทฅๅ…ท๏ผŒ**่ทณ่ฟ‡ AT2**๏ผŒ**่ทณ่ฟ‡ math**ใ€‚ๆต็จ‹ๅˆ†ไธบไธคๆญฅ๏ผšๅ…ˆ้‡‡ๆ ทๅนถ่ฟ‡ๆปค้ซ˜่ดจ้‡ CoT+boxed ็”Ÿๆˆ๏ผŒๅ†ๅฏน่ฟ‡ๆปค็ป“ๆžœๅšๅฝ’ๅ› ่ฏ„ไผฐใ€‚ + +ๆ”ฏๆŒๆ•ฐๆฎ้›†๏ผšMoreHopQAใ€HotpotQA๏ผˆRULER hotpotqa_long๏ผ‰ใ€RULER niah๏ผˆniah_*๏ผ‰ใ€RULER variable tracking๏ผˆvt_*๏ผ‰ใ€‚RULER ่ทฏๅพ„่‡ชๅŠจๅœจ `data/ruler_multihop//.../validation.jsonl` ไธญๆœ็ดขใ€‚ + +ไธป่ฆๆ–‡ไปถ๏ผš +- `sample_and_filter.py`๏ผš้‡‡ๆ ท + ๅˆคๅฎšไธ€่‡ดๆ€ง๏ผŒ่พ“ๅ‡บๅˆฐ `exp/exp2/data/` +- `run_exp.py`๏ผšๅฝ’ๅ› ๆต‹่ฏ•๏ผŒ่พ“ๅ‡บๅˆฐ `exp/exp2/output/` +- `dataset_utils.py`๏ผšๆ•ฐๆฎๅŠ ่ฝฝใ€็ญ”ๆกˆ span ่งฃๆž + +้‡‡ๆ ท่„šๆœฌๆ”ฏๆŒ็š„ๆ•ฐๆฎ้›† +- `morehopqa`๏ผˆๆœฌๅœฐ `data/with_human_verification.json`๏ผ‰ +- `hotpotqa_long`๏ผˆ่‡ชๅŠจๅœจ `data/ruler_multihop//hotpotqa_long/validation.jsonl` ๆœ็ดข๏ผ‰ +- `niah_*`๏ผˆRULER niah ๅ˜ไฝ“๏ผŒ่‡ชๅŠจๆœ็ดขๅŒไธŠ๏ผ‰ +- `vt_*`๏ผˆRULER variable tracking ๅ˜ไฝ“๏ผŒ่‡ชๅŠจๆœ็ดขๅŒไธŠ๏ผ‰ +- ็›ดๆŽฅไผ  RULER JSONL ่ทฏๅพ„๏ผˆไฝœไธบๆ•ฐๆฎ้›†ๅๅค„็†๏ผ‰๏ผŒๅ…ถไฝ™็ฑปๅž‹ไธๆ”ฏๆŒ + +ๅฝ’ๅ› ๆต‹่ฏ•ๆ”ฏๆŒ +- ๆ•ฐๆฎ้›†๏ผšไผ˜ๅ…ˆไฝฟ็”จ `exp/exp2/data/.jsonl` ็ผ“ๅญ˜๏ผŒ่‹ฅๆ— ๅˆ™ๆŒ‰้‡‡ๆ ทๅŒๆ ท็š„่งฃๆž่ง„ๅˆ™ๅŠ ่ฝฝ๏ผ›math ๆ˜พๅผๆ‹’็ปใ€‚ +- ๆŒ‡ๆ ‡๏ผš + - `faithfulness_gen`๏ผˆ็”Ÿๆˆไพง๏ผ‰๏ผšๅฏ่ฟ่กŒๅœจไปปไฝ•ๅทฒๅŠ ่ฝฝๆ ทๆœฌ๏ผˆmath ไปฅๅค–๏ผ‰ใ€‚ + - `recovery_ruler`๏ผˆๆขๅค็އ๏ผŒไป… RULER๏ผ‰๏ผšRecall@10%๏ผˆๆŽ’ๅๅชๅœจ prompt tokens ไธŠ่ฟ›่กŒ๏ผŒgold ๆฅ่‡ช `needle_spans`๏ผ‰ใ€‚ +- ๆ–นๆณ•๏ผˆ`--attr_funcs`๏ผ‰๏ผš`IG`ใ€`perturbation_all`ใ€`perturbation_CLP`ใ€`perturbation_REAGENT`ใ€`attention`๏ผˆๅ†…้ƒจ่žๅˆ IG๏ผ‰ใ€`ifr_all_positions`ใ€`ifr_multi_hop`ใ€`attnlrp`ใ€`ft_attnlrp`ใ€`basic`ใ€‚AT2 ๆœชๆไพ›ใ€‚ + +--- + +## ๆ•ฐๆฎ้‡‡ๆ ท + +ๅฎž็Žฐ้€ป่พ‘ +- ็ปŸไธ€ๆ•ฐๆฎๅŠ ่ฝฝ๏ผš`DatasetLoader` ่ฏปๅ– MoreHopQA / HotpotQA / RULER niah / RULER vt๏ผ›ๅฏ็›ดๆŽฅไผ ่‡ชๅฎšไน‰ RULER JSONLใ€‚ +- ็”Ÿๆˆๆจกๅž‹๏ผš`qwen3-235b-a22b-2507`๏ผˆ่‹ฑๆ–‡ system prompt๏ผ‰๏ผŒ่ฆๆฑ‚ใ€Œๅ…ˆ็ฎ€่ฆๆ€่€ƒ๏ผŒๅ†็”จ `\box{}` ๅŒ…่ฃนๆœ€็ปˆ็ญ”ๆกˆไธ”ๆœซๅฐพไธ่ฟฝๅŠ ๅ†…ๅฎนใ€๏ผ›user prompt ไธบๅŽŸ้ข˜๏ผŒๆ— ้ขๅค–ๆจกๆฟใ€‚ +- ๅˆคๅฎšๆจกๅž‹๏ผš`deepseek-v3-1-terminus`๏ผˆ่‹ฑๆ–‡ system prompt๏ผ‰๏ผŒๅช่พ“ๅ‡บ True/False ๅˆคๆ–ญ `\box{}` ๅ†…ๆ–‡ไธŽๅ‚่€ƒ็ญ”ๆกˆๆ˜ฏๅฆไธ€่‡ดใ€‚ +- ่ฟ‡ๆปค๏ผšไป…ไฟ็•™ใ€Œๆ€่€ƒ + ๆœซๅฐพ boxed ็ญ”ๆกˆใ€ไธ”ๅˆคๅฎšไธบ True ็š„ๆ ทๆœฌ๏ผ›`target` ็”จๆๅ–็š„ๆ€่€ƒ็‰‡ๆฎตไธŽ **ๅŽปๆމ box ๅŒ…่ฃน็š„ๆœ€็ปˆ็ญ”ๆกˆ** ้‡็ป„๏ผŒ้™„ๅธฆ token ็บง `sink_span`/`thinking_span`ใ€`reference_answer`ใ€`judge_response`๏ผˆไธๅ†ๅญ˜ `candidate_answer`๏ผ‰๏ผŒ`indices_to_explain` ็ปŸไธ€ๅ†™ไธบ `sink_span`๏ผˆboxed ๅ†…ๆ–‡ๅœจ `target` ็š„ generation token span๏ผŒ[start_tok, end_tok]๏ผ‰ใ€‚ +- ้‡‡ๆ ทไผšๆŒ‰ๅŽŸๅง‹้กบๅบไพๆฌกๅฐ่ฏ•ๆ ทๆœฌ๏ผŒๅˆคๅฎšๅคฑ่ดฅ็ซ‹ๅณ่ทณ่ฟ‡๏ผ›็ดฏ่ฎกๅˆฐ `--max_examples` ๆกๆˆๅŠŸๆ ทๆœฌๅณๆๅ‰ๅœๆญข๏ผˆ่‹ฅๆบๆ•ฐๆฎไธ่ถณๅˆ™ๆ›ดๅฐ‘๏ผ‰๏ผŒtqdm ไผšๅˆ†ๅˆซๆ˜พ็คบๅฐ่ฏ•ไธŽๆˆๅŠŸ่ฎกๆ•ฐใ€‚ + +ไฝฟ็”จ่ฏดๆ˜Ž +```bash +export FLASHTRACE_API_KEY=sk-yaojia-get-ccfa # ๆˆ– OPENAI_API_KEY + +# ็คบไพ‹๏ผš้‡‡ๆ ท hotpotqa_long๏ผŒไฟ็•™ๆœ€ๅคš 100 ๆกๅˆคๅฎšไธบ True ็š„ๆ ทๆœฌ +python exp/exp2/sample_and_filter.py \ + --dataset data/with_human_verification.json \ + --max_examples 100 \ + --api_key sk-yaojia-get-ccfa \ + --tokenizer_model /opt/share/models/Qwen/Qwen3-8B > exp/exp2/out.log +``` +ๅธธ็”จๅ‚ๆ•ฐ๏ผš +- `--dataset`๏ผšmorehopqa | hotpotqa_long | niah_* | vt_*๏ผˆๆˆ–็›ดๆŽฅ JSONL ่ทฏๅพ„๏ผ‰ +- `--max_examples`๏ผšๅธŒๆœ›ไฟ็•™็š„ๆˆๅŠŸๆ ทๆœฌๆ•ฐ๏ผ›่พพๅˆฐๅŽๅณๅœๆญข๏ผˆ่‹ฅๆบๆ•ฐๆฎไธ่ถณๅˆ™ๆ›ดๅฐ‘๏ผ‰ +- `--tokenizer_model`๏ผš็”จไบŽ span ๆฃ€ๆต‹็š„ tokenizer๏ผˆ้ป˜่ฎคๅค็”จ็”Ÿๆˆๆจกๅž‹๏ผ‰ +- `--api_base`/`--api_key`๏ผšๆŽฅๅฃๅœฐๅ€ไธŽๅฏ†้’ฅ๏ผˆ้ป˜่ฎคๆœฌๅœฐ http://localhost:4000/v1๏ผ‰ +- `--request_interval` / `--judge_interval`๏ผš็”Ÿๆˆ/ๅˆคๅฎš้—ด้š”่Š‚ๆต๏ผˆ้ป˜่ฎค 1s๏ผ‰ +- `--rate_limit_delay`๏ผš้‡ๅˆฐ HTTP 429 ๆ—ถ็š„็ญ‰ๅพ…็ง’ๆ•ฐ๏ผˆ้ป˜่ฎค 5s๏ผ‰๏ผ›ไผšๅœจ้‡่ฏ•ๅ‰่‡ชๅŠจ sleep +่พ“ๅ‡บ๏ผš`exp/exp2/data/.jsonl` + +--- + +## ๅฝ’ๅ› ๆต‹่ฏ• + +ๅฎž็Žฐ้€ป่พ‘ +- ่พ“ๅ…ฅ๏ผšไผ˜ๅ…ˆ่ฏปๅ– `exp/exp2/data/.jsonl`๏ผˆ่ฟ‡ๆปค็ผ“ๅญ˜๏ผ‰๏ผ›่‹ฅไธๅญ˜ๅœจๅˆ™ๅ›ž้€€ๅˆฐๅŽŸๅง‹ๆ•ฐๆฎ่งฃๆžใ€‚ +- ๆ–นๆณ•๏ผšๅฟ ๅฎžๅบฆ๏ผˆtoken-level RISE/MAS๏ผ‰ๅฏน้ฝ `evaluations/faithfulness.py` ็š„้€ป่พ‘๏ผˆAT2 ๆœชๅฎž็Žฐ๏ผ‰๏ผŒmath ่‡ชๅŠจๆ‹’็ปใ€‚ +- ๅคš่ทณ FlashTrace๏ผš่‹ฅ็ผ“ๅญ˜ๅซ `sink_span`/`thinking_span` ๅˆ™็”จไบŽ multi-hop IFR๏ผŒๅฆๅˆ™้ป˜่ฎคๆ•ดๅฅ็ญ”ๆกˆไธบ sinkใ€‚ +- ไธ€ๆฌก่ฟ่กŒๅฏๅŒๆ—ถ่ฏ„ๆต‹ๅคšไธชๆŒ‡ๆ ‡๏ผš`--mode` ๆ”ฏๆŒๅคšๅ€ผไธŽ้€—ๅทๅˆ†้š”๏ผˆๅฆ‚ `--mode faithfulness_gen,recovery_ruler` ๆˆ– `--mode faithfulness_gen, recovery_ruler`๏ผ‰๏ผŒๅฏนๅŒไธ€ๆ‰นๆ ทๆœฌๅชๅšไธ€ๆฌกๅฝ’ๅ› ใ€‚ +- ๅฏ้€‰ไฟๅญ˜ๆ ทๆœฌ็บง trace๏ผšๅŠ  `--save_hop_traces` ไผšไธบ**ๆ‰€ๆœ‰ๆ–นๆณ•ใ€ๆ‰€ๆœ‰ๆ ทๆœฌ**ไฟๅญ˜ๅฝ’ๅ› ๅ‘้‡ไธŽ้€ๆ ทๆœฌๆŒ‡ๆ ‡ๅˆฐ `exp/exp2/output/traces/...`๏ผ›ๅฏน multi-hop ๆ–นๆณ•่ฟ˜ไผš้ขๅค–ไฟๅญ˜ๆฏ่ทณ็š„ token-level ๅ‘้‡ `V_h`๏ผˆๅ•ไธ€ `vh`๏ผŒๅณๅฎž้™…ๅ‚ไธŽๅคš่ทณไผ ๆ’ญ็š„ๅ‘้‡๏ผ‰๏ผŒๅนถๅœจ manifest ไธญ่ฎฐๅฝ• `attnlrp_neg_handling/attnlrp_norm_mode` ็ญ‰่ฎพ็ฝฎใ€‚ +- ๅทฒ็Ÿฅๅ…ผๅฎนๆ€ง๏ผš้ƒจๅˆ† tokenizer ๅœจ chat template ่พน็•Œไผšๅ‡บ็Žฐ token ๅˆๅนถ๏ผŒๅฏผ่‡ด่ฏ„ๆต‹ไพง็”จ token-id ๅญๅบๅˆ—ๅฎšไฝ user prompt ๅคฑ่ดฅ๏ผ›exp2 ๅทฒๆ”นไธบ็›ดๆŽฅๅค็”จๅฝ’ๅ› ้˜ถๆฎต็ฎ—ๅ‡บ็š„ `user_prompt_indices` ๅšๆ‰ฐๅŠจๅฎšไฝใ€‚ +- ๆ‰นๅคงๅฐไผฐ็ฎ—๏ผšๆฒฟ็”จๅŽŸ่„šๆœฌ `(max_input_len-100)/len(tokenizer(format_prompt(prompt)+target))` ็š„ไฟๅฎˆไผฐ่ฎก๏ผˆ่‡ณๅฐ‘ 1๏ผ‰ใ€‚`max_input_len` ็”ฑไปฃ็ ๅ†…็ฝฎๆ˜ ๅฐ„่กจๅŸบไบŽ `--model` ๅญ—็ฌฆไธฒๅ†ณๅฎš๏ผŒๆœชๅ‘ฝไธญๆˆ–ไป…ไผ  `--model_path` ๆ—ถ้ป˜่ฎค 2000๏ผ›ๅฆ‚้œ€ๆ˜ ๅฐ„ๅ€ผ่€Œๅˆ็”จๆœฌๅœฐ่ทฏๅพ„๏ผŒ่ฏทๅŒๆ—ถไผ ๅ…ฅๅฏนๅบ”็š„ `--model` ๅ็งฐใ€‚ +- ่ฎกๆ—ถ๏ผšๅฏนๆฏไธชๆ ทๆœฌ็š„ๅฝ’ๅ› ่ฎก็ฎ—๏ผˆrecovery/faithfulness๏ผ‰ๅˆ†ๅˆซ่ฎกๆ—ถ๏ผŒๆœ€็ปˆๅœจ CSV ๆœซๅฐพ่ฟฝๅŠ  `Avg Sample Time (s)` ๅนถๅœจๆŽงๅˆถๅฐๆ‰“ๅฐๅนณๅ‡่€—ๆ—ถใ€‚ +- ่พ“ๅ‡บ๏ผš`exp/exp2/output/faithfulness/...`ใ€`exp/exp2/output/recovery/...`๏ผŒไปฅๅŠ๏ผˆๅฏ้€‰๏ผ‰`exp/exp2/output/traces/...`๏ผŒๆŒ‰ๆ•ฐๆฎ้›†ๅ’Œๆจกๅž‹ๅˆ†็›ฎๅฝ•ใ€‚ + +ไฝฟ็”จ่ฏดๆ˜Ž +```bash +# ็”Ÿๆˆไพง RISE/MAS ๅฟ ๅฎžๅบฆ perturbation_all_fast,perturbation_CLP_fast,perturbation_REAGENT_fast,ifr_multi_hop_stop_words,ifr_multi_hop_both,ifr_multi_hop_split_hop,ft_attnlrp,ifr_multi_hop,attnlrp,ifr_all_positions,perturbation_all,perturbation_REAGENT,perturbation_CLP,IG,attention +python exp/exp2/run_exp.py \ + --datasets exp/exp2/data/math.jsonl \ + --attr_funcs IG,attention \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 2,3,4,5,6,7 \ + --num_examples 100 \ + --mode faithfulness_gen \ + --n_hops 1 \ + --save_hop_traces \ +&& python exp/exp2/run_exp.py \ + --datasets exp/exp2/data/morehopqa.jsonl \ + --attr_funcs IG,attention \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 2,3,4,5,6,7 \ + --num_examples 100 \ + --mode faithfulness_gen \ + --n_hops 1 \ + --save_hop_traces + + # --attnlrp_neg_handling drop \ + # --attnlrp_norm_mode norm +``` +ๅธธ็”จๅ‚ๆ•ฐ๏ผš +- `--datasets`๏ผš้€—ๅทๅˆ†้š”ๆ•ฐๆฎ้›†ๅ๏ผ›่‹ฅๅทฒๅญ˜ๅœจ `exp/exp2/data/.jsonl` ๅˆ™็›ดๆŽฅไฝฟ็”จใ€‚ +- `--attr_funcs`๏ผš้€—ๅทๅˆ†้š”ๆ–นๆณ•๏ผˆๆ—  AT2๏ผ‰๏ผ›`ifr_multi_hop` ไธŽ `ft_attnlrp` ๆ”ฏๆŒๅคš่ทณ๏ผˆ็”ฑ `--n_hops` ๆŽงๅˆถ๏ผ‰ใ€‚ +- `--attnlrp_neg_handling`๏ผšFT-AttnLRP ๆฏ่ทณ่ดŸๅ€ผๅค„็†๏ผˆ`drop`/`abs`๏ผ‰ใ€‚ +- `--attnlrp_norm_mode`๏ผšFT-AttnLRP ๆญฃๅˆ™ๅŒ–ไธŽ hop ratio ๅผ€ๅ…ณ๏ผˆ`norm`/`no_norm`๏ผ‰ใ€‚ +- `--data_root`/`--output_root`๏ผš็ผ“ๅญ˜ไธŽ็ป“ๆžœ็›ฎๅฝ•๏ผˆ้ป˜่ฎค `exp/exp2/data` / `exp/exp2/output`๏ผ‰ใ€‚ +- `--mode`๏ผš`faithfulness_gen`ใ€`recovery_ruler`๏ผŒๅฏๅคšๅ€ผ/้€—ๅทๅˆ†้š”๏ผˆไธ€ๆฌกๅฝ’ๅ› ๅŒๆ—ถ่พ“ๅ‡บๅคšไธชๆŒ‡ๆ ‡๏ผ‰๏ผ›`--num_examples` ๆŽงๅˆถ่ฏ„ๆต‹ๆกๆ•ฐใ€‚math ไผš่ขซๆ‹’็ปใ€‚*** +- `--save_hop_traces`๏ผšไฟๅญ˜ๆ ทๆœฌ็บง trace ๅˆฐ `exp/exp2/output/traces////`๏ผˆๆฏๆ ทๆœฌ `ex_*.npz` + `manifest.jsonl`๏ผ‰ใ€‚ diff --git a/exp/exp2/dataset_utils.py b/exp/exp2/dataset_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..3590c8a50b981dde4a653b62cb56d59c7bb197a1 --- /dev/null +++ b/exp/exp2/dataset_utils.py @@ -0,0 +1,386 @@ +"""Dataset helpers for Experiment 2 (CoT / multi-hop faithfulness). + +Named dataset_utils to avoid collision with the HF `datasets` package. +""" + +from __future__ import annotations + +import json +import random +import re +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Dict, Iterable, List, Optional + +from attribution_datasets import ( + AttributionExample, + MoreHopQAAttributionDataset, + RulerAttributionDataset, +) + + +@dataclass +class CachedExample: + prompt: str + target: Optional[str] + indices_to_explain: Optional[List[int]] + attr_mask_indices: Optional[List[int]] + sink_span: Optional[List[int]] + thinking_span: Optional[List[int]] + metadata: Dict[str, Any] + + +def read_cached_jsonl(path: Path) -> List[CachedExample]: + examples: List[CachedExample] = [] + with path.open("r", encoding="utf-8") as f: + for line in f: + if not line.strip(): + continue + obj = json.loads(line) + examples.append( + CachedExample( + prompt=obj["prompt"], + target=obj.get("target"), + indices_to_explain=obj.get("indices_to_explain"), + attr_mask_indices=obj.get("attr_mask_indices"), + sink_span=obj.get("sink_span"), + thinking_span=obj.get("thinking_span"), + metadata=obj.get("metadata", {}), + ) + ) + return examples + + +def load_cached(path: Path, sample: Optional[int] = None, seed: int = 42) -> List[CachedExample]: + ex = read_cached_jsonl(path) + if sample is not None and sample < len(ex): + random.Random(seed).shuffle(ex) + ex = ex[:sample] + return ex + + +def load_ruler(path: Path, sample: Optional[int] = None, seed: int = 42) -> List[CachedExample]: + ds = RulerAttributionDataset(path) + examples: List[CachedExample] = [] + ex_iter: Iterable[AttributionExample] = ds + if sample is not None and sample < len(ds): + ex_iter = list(ds) + random.Random(seed).shuffle(ex_iter) + ex_iter = ex_iter[:sample] + for ex in ex_iter: + examples.append( + CachedExample( + prompt=ex.prompt, + target=ex.target, + indices_to_explain=ex.indices_to_explain, + attr_mask_indices=ex.attr_mask_indices, + sink_span=None, + thinking_span=None, + metadata=ex.metadata, + ) + ) + return examples + + +def load_morehopqa( + path: str | Path = "./data/with_human_verification.json", sample: Optional[int] = None, seed: int = 42 +) -> List[CachedExample]: + ds = MoreHopQAAttributionDataset(path) + ex_iter: Iterable[AttributionExample] = ds + if sample is not None and sample < len(ds): + ex_iter = list(ds) + random.Random(seed).shuffle(ex_iter) + ex_iter = ex_iter[:sample] + examples: List[CachedExample] = [] + for ex in ex_iter: + examples.append( + CachedExample( + prompt=ex.prompt, + target=None, + indices_to_explain=ex.indices_to_explain, + attr_mask_indices=ex.attr_mask_indices, + sink_span=None, + thinking_span=None, + metadata=ex.metadata, + ) + ) + return examples + + +def auto_find_ruler(task: str) -> Optional[Path]: + length_dirs = ["4096", "8192", "16384", "32768", "65536", "131072"] + base = Path("data/ruler_multihop") + for ld in length_dirs: + cand = base / ld / task / "validation.jsonl" + if cand.exists(): + return cand + return None + + +def dataset_from_name(name: str) -> Optional[Path]: + if name == "hotpotqa_long": + return auto_find_ruler("hotpotqa_long") + if name.startswith("vt_"): + return auto_find_ruler(name) + if name.startswith("niah"): + return auto_find_ruler(name) + p = Path(name) + if p.exists(): + return p + return None + + +_BOX_PATTERN = re.compile(r"\\box(?:ed)?\s*[\{๏ฝ›](.*?)[\}๏ฝ]", flags=re.DOTALL) + + +def _find_box_span(text: str) -> Optional[tuple[int, int, str]]: + """Return (start_char, end_char, answer_text) for the last \\boxed block.""" + matches = list(_BOX_PATTERN.finditer(text)) + if not matches: + return None + m = matches[-1] + return m.start(0), m.end(0), m.group(1).strip() + + +def extract_boxed_answer(text: str) -> Optional[str]: + """Extract the answer string inside the last \\boxed{} block.""" + match = _find_box_span(text) + return match[2] if match else None + + +def _find_answer_span(text: str, answer: str) -> Optional[tuple[int, int]]: + """Return (start_char, end_char) for the last occurrence of `answer` in text.""" + if not answer or not text: + return None + start = text.rfind(answer) + if start == -1: + return None + return start, start + len(answer) + + +def split_boxed_generation(text: str) -> Optional[tuple[str, str, str]]: + """Return (thinking_text, boxed_segment, boxed_answer) if format matches.""" + if not text: + return None + match = _find_box_span(text) + if not match: + return None + + start_char, end_char, boxed_inner = match + boxed_segment = text[start_char:end_char].strip() + thinking_text = text[:start_char].strip() + trailing = text[end_char:].strip() + + if not boxed_inner or not boxed_segment: + return None + if trailing: + return None + if not thinking_text: + return None + + return thinking_text, boxed_segment, boxed_inner + + +def attach_spans_from_answer( + example: CachedExample, tokenizer, answer_text: Optional[str] = None +) -> CachedExample: + """Attach sink/thinking spans by locating the (plain) answer in `target`. + + `answer_text` should be the extracted boxed answer; falls back to metadata or + parsing the target when omitted. Works even when the target no longer keeps + the \\box{} wrapper. + """ + tgt = example.target or "" + answer = (answer_text or "").strip() + if not answer: + answer = (example.metadata.get("boxed_answer") or extract_boxed_answer(tgt) or "").strip() + + metadata = dict(example.metadata) + if answer: + metadata.setdefault("boxed_answer", answer) + + if tokenizer is None or not tgt or not answer: + return CachedExample( + prompt=example.prompt, + target=example.target, + indices_to_explain=example.indices_to_explain, + attr_mask_indices=example.attr_mask_indices, + sink_span=example.sink_span, + thinking_span=example.thinking_span, + metadata=metadata, + ) + + span = _find_answer_span(tgt, answer) + if span is None: + return CachedExample( + prompt=example.prompt, + target=example.target, + indices_to_explain=example.indices_to_explain, + attr_mask_indices=example.attr_mask_indices, + sink_span=example.sink_span, + thinking_span=example.thinking_span, + metadata=metadata, + ) + + span_start_char, span_end_char = span + gen_ids = tokenizer(tgt, add_special_tokens=False, return_offsets_mapping=True) + sink_tokens: List[int] = [] + for idx, (s, e) in enumerate(gen_ids["offset_mapping"]): + # include tokens that overlap the answer span + if s < span_end_char and e > span_start_char: + sink_tokens.append(idx) + if not sink_tokens: + return CachedExample( + prompt=example.prompt, + target=example.target, + indices_to_explain=example.indices_to_explain, + attr_mask_indices=example.attr_mask_indices, + sink_span=example.sink_span, + thinking_span=example.thinking_span, + metadata=metadata, + ) + + sink_span = [min(sink_tokens), max(sink_tokens)] + thinking_end = max(0, sink_span[0] - 1) + thinking_span = [0, thinking_end] if thinking_end >= 0 else sink_span + + return CachedExample( + prompt=example.prompt, + target=example.target, + indices_to_explain=example.indices_to_explain, + attr_mask_indices=example.attr_mask_indices, + sink_span=example.sink_span or sink_span, + thinking_span=example.thinking_span or thinking_span, + metadata=metadata, + ) + + +def attach_spans_from_boxed(example: CachedExample, tokenizer) -> CachedExample: + """Backward-compatible wrapper that first looks for \\box{} then falls back to answer text.""" + tgt = example.target + match = _find_box_span(tgt) if tgt else None + boxed_answer = match[2] if match else None + return attach_spans_from_answer(example, tokenizer, boxed_answer) + + +def ruler_gold_prompt_token_indices(example: CachedExample, tokenizer) -> List[int]: + """Return token indices (prompt-side) that overlap RULER `needle_spans` in metadata. + + The returned indices are with respect to `tokenizer(" " + example.prompt, add_special_tokens=False)`, + matching the attribution pipeline's leading-space convention. + """ + needle_spans = (example.metadata or {}).get("needle_spans") or [] + if not isinstance(needle_spans, list) or not needle_spans: + return [] + + prompt_text = " " + (example.prompt or "") + enc = tokenizer(prompt_text, add_special_tokens=False, return_offsets_mapping=True) + offsets = enc.get("offset_mapping") + if offsets is None: + raise ValueError("Tokenizer does not provide offset_mapping; cannot map needle_spans to tokens.") + + spans: List[tuple[int, int]] = [] + for item in needle_spans: + if not isinstance(item, dict): + continue + raw = item.get("span") + if not (isinstance(raw, list) and len(raw) == 2): + continue + try: + start = int(raw[0]) + 1 # shift for leading space in prompt_text + end = int(raw[1]) + 1 + except Exception: + continue + if end > start: + spans.append((start, end)) + + if not spans: + return [] + + gold: set[int] = set() + for tok_idx, off in enumerate(offsets): + if off is None: + continue + try: + s, e = int(off[0]), int(off[1]) + except Exception: + continue + if e <= s: + continue + for span_start, span_end in spans: + if s < span_end and e > span_start: + gold.add(tok_idx) + break + + return sorted(gold) + + +class DatasetLoader: + """Thin loader that resolves and samples datasets for exp2.""" + + def __init__(self, seed: int = 42, data_root: Path | str = Path("exp/exp2/data")) -> None: + self.seed = seed + self.data_root = Path(data_root) + + def _sample(self, items: List[CachedExample], sample: Optional[int]) -> List[CachedExample]: + if sample is not None and sample < len(items): + rnd = random.Random(self.seed) + rnd.shuffle(items) + items = items[:sample] + return items + + def _cached_path(self, name: str) -> Optional[Path]: + path = self.data_root / f"{name}.jsonl" + return path if path.exists() else None + + def load(self, name: str, sample: Optional[int] = None) -> List[CachedExample]: + # 1) Prefer prepared cache under exp/exp2/data + cached_path = self._cached_path(name) + if cached_path: + return self._sample(load_cached(cached_path), sample) + + return self.load_raw(name, sample=sample) + + def load_raw(self, name: str, sample: Optional[int] = None) -> List[CachedExample]: + def _looks_like_json_array(path: Path) -> bool: + try: + with path.open("r", encoding="utf-8") as f: + while True: + ch = f.read(1) + if not ch: + return False + if ch.isspace(): + continue + return ch == "[" + except OSError: + return False + + # MoreHopQA + if name == "morehopqa": + ex = load_morehopqa() + for item in ex: + if "answer" in item.metadata: + item.metadata.setdefault("reference_answer", item.metadata["answer"]) + return self._sample(ex, sample) + + # Allow passing the raw MoreHopQA JSON path directly. + p = Path(name) + if p.exists() and _looks_like_json_array(p): + ex = load_morehopqa(p) + for item in ex: + if "answer" in item.metadata: + item.metadata.setdefault("reference_answer", item.metadata["answer"]) + return self._sample(ex, sample) + + # RULER / HotpotQA / niah / vt (all go through RulerAttributionDataset) + resolved = dataset_from_name(name) + if resolved is None: + raise FileNotFoundError(f"Could not resolve dataset {name}") + ex = load_ruler(resolved) + for item in ex: + outputs = item.metadata.get("outputs") or [] + if outputs: + item.metadata.setdefault("reference_answer", ", ".join(outputs)) + if item.target and "reference_answer" not in item.metadata: + item.metadata["reference_answer"] = item.target + return self._sample(ex, sample) diff --git a/exp/exp2/map_math_mine_to_exp2_cache.py b/exp/exp2/map_math_mine_to_exp2_cache.py new file mode 100644 index 0000000000000000000000000000000000000000..7266708c1007149d2194d52f2ff420321a020ec8 --- /dev/null +++ b/exp/exp2/map_math_mine_to_exp2_cache.py @@ -0,0 +1,584 @@ +#!/usr/bin/env python3 +"""Prepare data/math_mine.json into an exp2 cached JSONL dataset. + +This script supports two modes: + +- map (offline): convert GSM8K-style math examples: + + {"question": "...", "answer": "... #### 18"} + + into exp2's cached JSONL format (one JSON object per line). + +- resample (online): resample targets like exp/exp2/sample_and_filter.py: + call a chat completion API to generate " + final \\box{} answer", + judge the boxed answer against the reference answer extracted from the raw + GSM8K-style entry, and write only judge=True samples. + +In both modes, exp2 expects token-level spans (NOT character spans): + + - indices_to_explain: [start_tok, end_tok] (generation-token indices, closed interval) + - sink_span/thinking_span: token spans over tokenizer(target, add_special_tokens=False) +""" + +from __future__ import annotations + +import argparse +import json +import os +import sys +import time +import urllib.error +import urllib.request +from dataclasses import asdict +from pathlib import Path +from typing import Any, Dict, List, Optional, Tuple + +from transformers import AutoTokenizer +from tqdm import tqdm + +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + +from exp.exp2.dataset_utils import CachedExample, attach_spans_from_answer, split_boxed_generation # noqa: E402 + + +class RateLimitError(RuntimeError): + """Raised when API returns 429; carries a suggested wait time.""" + + def __init__(self, wait_seconds: float, detail: str) -> None: + super().__init__(detail) + self.wait_seconds = wait_seconds + + +GEN_SYSTEM_PROMPT = ( + "You are a reasoning assistant. " + "Before answering, engage in an chain of thought. " + "Process this freely and naturally without using specific headers or strict formatting. " + "When you reach the conclusion, wrap the entire final sentence containing the answer inside \\box{}. " + "Ensure the box wraps the **sentence** that naturally delivers the answer. DO NOT rewrite the answer word for the box separately." +) + +JUDGE_SYSTEM_PROMPT = ( + "You verify whether the model's boxed answer matches the reference answer. " + "Reply strictly with True or False and nothing else." +) + + +def call_chat_api( + api_base: str, + api_key: str, + model: str, + messages: List[Dict[str, str]], + *, + timeout: int, + max_tokens: int, + temperature: float, + cache_ttl: int, + cache_namespace: Optional[str], + rate_limit_delay: Optional[float] = None, +) -> str: + """Minimal OpenAI-compatible chat.completions client (no external deps).""" + url = api_base.rstrip("/") + "/chat/completions" + payload: Dict[str, Any] = { + "model": model, + "messages": messages, + "max_tokens": max_tokens, + "temperature": temperature, + } + if cache_ttl > 0: + cache_obj: Dict[str, Any] = {"ttl": cache_ttl} + if cache_namespace: + cache_obj["namespace"] = cache_namespace + payload["cache"] = cache_obj + + data = json.dumps(payload).encode("utf-8") + headers = {"Content-Type": "application/json"} + if api_key: + headers["Authorization"] = f"Bearer {api_key}" + + req = urllib.request.Request(url, data=data, headers=headers, method="POST") + opener = urllib.request.build_opener(urllib.request.ProxyHandler({})) + try: + with opener.open(req, timeout=timeout) as resp: + resp_bytes = resp.read() + except urllib.error.HTTPError as e: + detail = e.read().decode("utf-8", errors="ignore") if hasattr(e, "read") else "" + if e.code == 429: + retry_after = None + if hasattr(e, "headers") and e.headers: + retry_after_header = e.headers.get("Retry-After") + if retry_after_header: + try: + retry_after = float(retry_after_header) + except ValueError: + retry_after = None + wait = retry_after or rate_limit_delay or 5.0 + raise RateLimitError(wait, f"API HTTP 429: {detail}") from e + raise RuntimeError(f"API HTTP error {e.code}: {detail}") from e + except urllib.error.URLError as e: + raise RuntimeError(f"API request failed: {e}") from e + + try: + response = json.loads(resp_bytes.decode("utf-8")) + except json.JSONDecodeError as e: + raise RuntimeError(f"Failed to decode API response: {resp_bytes!r}") from e + + choices = response.get("choices", []) + if not choices: + raise RuntimeError(f"Empty choices from API: {response}") + content = choices[0].get("message", {}).get("content", "") + if not content: + raise RuntimeError(f"Empty content from API: {response}") + return content.strip() + + +def build_gen_messages(prompt: str) -> List[Dict[str, str]]: + return [ + {"role": "system", "content": GEN_SYSTEM_PROMPT}, + {"role": "user", "content": prompt}, + ] + + +def build_judge_messages(reference_answer: str, candidate_answer: str) -> List[Dict[str, str]]: + user = ( + "Decide if the model's boxed answer matches the reference answer.\n" + f"Reference answer: {reference_answer}\n" + f"Model boxed answer (only the content inside \\box{{}}): {candidate_answer}\n" + "Output only True if they are semantically consistent; otherwise output False." + ) + return [ + {"role": "system", "content": JUDGE_SYSTEM_PROMPT}, + {"role": "user", "content": user}, + ] + + +def parse_bool(text: str) -> bool: + first = text.strip().splitlines()[0].strip().lower() + if first in {"true", "yes"}: + return True + if first in {"false", "no"}: + return False + # fallback: check substring + if "true" in first and "false" not in first: + return True + if "false" in first: + return False + raise ValueError(f"Cannot parse boolean from: {text!r}") + + +def _load_tokenizer(tokenizer_model: str): + tok_path = Path(tokenizer_model) + if tok_path.exists(): + tokenizer = AutoTokenizer.from_pretrained(tok_path.as_posix(), local_files_only=True) + else: + tokenizer = AutoTokenizer.from_pretrained(tokenizer_model) + if tokenizer.pad_token is None and tokenizer.eos_token is not None: + tokenizer.pad_token = tokenizer.eos_token + return tokenizer + + +def _split_gsm8k_answer(answer: str) -> Optional[Tuple[str, str]]: + """Return (thinking_text, final_answer) parsed from GSM8K `answer`.""" + text = (answer or "").strip() + if not text: + return None + if "####" not in text: + return None + thinking, final = text.rsplit("####", 1) + thinking = thinking.strip() + final = final.strip() + if not final: + return None + return thinking, final + + +def _is_token_span(span: Any) -> bool: + return isinstance(span, list) and len(span) == 2 and all(isinstance(x, int) for x in span) + + +def _build_cached_example( + *, + question: str, + answer: str, + tokenizer, + example_idx: int, + source_path: str, +) -> Optional[CachedExample]: + parsed = _split_gsm8k_answer(answer) + if parsed is None: + return None + thinking_text, final_answer = parsed + + prompt = question.strip() + target = f"{thinking_text}\n{final_answer}" if thinking_text else final_answer + + example = CachedExample( + prompt=prompt, + target=target, + indices_to_explain=None, + attr_mask_indices=None, + sink_span=None, + thinking_span=None, + metadata={ + "dataset": "math_mine", + "source_path": source_path, + "example_idx": int(example_idx), + "raw_question": question, + "raw_answer": answer, + "reference_answer": final_answer, + "boxed_answer": final_answer, + }, + ) + example = attach_spans_from_answer(example, tokenizer, final_answer) + if not _is_token_span(example.sink_span): + return None + + # exp2 requires token-level indices_to_explain=[start_tok,end_tok] (closed interval). + indices_to_explain = list(example.sink_span) + thinking_span = example.thinking_span + if thinking_span is not None and _is_token_span(thinking_span) and indices_to_explain[0] == 0: + # No room for "thinking" tokens; avoid overlapping spans. + thinking_span = None + + return CachedExample( + prompt=example.prompt, + target=example.target, + indices_to_explain=indices_to_explain, + attr_mask_indices=example.attr_mask_indices, + sink_span=indices_to_explain, + thinking_span=thinking_span, + metadata=example.metadata, + ) + + +def _build_resampled_example( + *, + question: str, + raw_answer: str, + reference_answer: str, + generation: str, + tokenizer, + example_idx: int, + source_path: str, + judge_response: str, + generator_model: str, + judge_model: str, +) -> Optional[CachedExample]: + parsed = split_boxed_generation(generation) + if not parsed: + return None + + thinking_text, _boxed_segment, boxed_answer = parsed + target_text = f"{thinking_text}\n{boxed_answer}" if thinking_text else boxed_answer + + example = CachedExample( + prompt=question.strip(), + target=target_text, + indices_to_explain=None, + attr_mask_indices=None, + sink_span=None, + thinking_span=None, + metadata={ + "dataset": "math_mine", + "source_path": source_path, + "example_idx": int(example_idx), + "raw_question": question, + "raw_answer": raw_answer, + "reference_answer": reference_answer, + "judge_response": judge_response, + "generator_model": generator_model, + "judge_model": judge_model, + }, + ) + example = attach_spans_from_answer(example, tokenizer, boxed_answer) + if not _is_token_span(example.sink_span): + return None + + indices_to_explain = list(example.sink_span) + return CachedExample( + prompt=example.prompt, + target=example.target, + indices_to_explain=indices_to_explain, + attr_mask_indices=example.attr_mask_indices, + sink_span=indices_to_explain, + thinking_span=example.thinking_span, + metadata=example.metadata, + ) + + +def _write_jsonl(path: Path, *, examples) -> int: + path.parent.mkdir(parents=True, exist_ok=True) + count = 0 + with path.open("w", encoding="utf-8") as f: + for ex in examples: + f.write(json.dumps(asdict(ex), ensure_ascii=False) + "\n") + count += 1 + return count + + +def main() -> None: + ap = argparse.ArgumentParser("Prepare data/math_mine.json for exp2 cached JSONL.") + ap.add_argument("--in_json", type=str, default="data/math_mine.json") + ap.add_argument("--out_jsonl", type=str, default="exp/exp2/data/math.jsonl") + ap.add_argument( + "--tokenizer_model", + type=str, + required=True, + help="Tokenizer name or local path; must match the tokenizer used in exp2 attribution.", + ) + ap.add_argument( + "--mode", + type=str, + choices=["map", "resample"], + default="map", + help="map=offline mapping from GSM8K answers; resample=generate+judge like exp/exp2/sample_and_filter.py.", + ) + + # Resample (online) options (kept compatible with exp/exp2/sample_and_filter.py). + ap.add_argument("--max_examples", type=int, default=100, help="Number of judge=True examples to keep (resample mode).") + ap.add_argument("--seed", type=int, default=42, help="Shuffle seed (only used with --shuffle).") + ap.add_argument("--shuffle", action="store_true", help="Shuffle examples before attempting (resample mode).") + ap.add_argument("--api_base", type=str, default="http://localhost:4000/v1", help="Chat API base URL.") + ap.add_argument("--api_key", type=str, default=None, help="API key; defaults to FLASHTRACE_API_KEY/OPENAI_API_KEY.") + ap.add_argument("--generator_model", type=str, default="qwen3-235b-a22b-2507") + ap.add_argument("--judge_model", type=str, default="deepseek-v3-1-terminus") + ap.add_argument("--api_timeout", type=int, default=300) + ap.add_argument("--api_max_tokens", type=int, default=8192) + ap.add_argument("--api_temperature", type=float, default=0.0) + ap.add_argument("--api_cache_ttl", type=int, default=600) + ap.add_argument("--api_cache_namespace", type=str, default="flashtrace-exp2") + ap.add_argument("--retry_delay", type=float, default=2.0) + ap.add_argument("--retries", type=int, default=2, help="Additional retries on API failure.") + ap.add_argument("--request_interval", type=float, default=1.0, help="Sleep seconds between generation calls.") + ap.add_argument("--judge_interval", type=float, default=1.0, help="Sleep seconds between judge calls.") + ap.add_argument("--rate_limit_delay", type=float, default=5.0, help="Seconds to wait on HTTP 429 before retrying.") + args = ap.parse_args() + + in_path = Path(args.in_json) + out_path = Path(args.out_jsonl) + tokenizer = _load_tokenizer(args.tokenizer_model) + + raw = json.loads(in_path.read_text(encoding="utf-8")) + if not isinstance(raw, list): + raise SystemExit(f"Expected a JSON array in {in_path}, got {type(raw).__name__}.") + + source_total = len(raw) + total = 0 + kept = 0 + skipped_empty_q = 0 + skipped_empty_a = 0 + skipped_parse = 0 + skipped_span = 0 + + examples = [] + if args.mode == "map": + attempted = None + skipped_format = None + judged_false = None + for idx, item in enumerate(raw): + total += 1 + if not isinstance(item, dict): + skipped_parse += 1 + continue + + question = str(item.get("question") or "") + answer = str(item.get("answer") or "") + if not question.strip(): + skipped_empty_q += 1 + continue + if not answer.strip(): + skipped_empty_a += 1 + continue + + ex = _build_cached_example( + question=question, + answer=answer, + tokenizer=tokenizer, + example_idx=idx, + source_path=str(in_path), + ) + if ex is None: + # distinguish parse-vs-span failure + parsed = _split_gsm8k_answer(answer) + if parsed is None: + skipped_parse += 1 + else: + skipped_span += 1 + continue + + examples.append(ex) + kept += 1 + else: + api_key = args.api_key or os.environ.get("FLASHTRACE_API_KEY") or os.environ.get("OPENAI_API_KEY") + if not api_key: + raise SystemExit("resample mode requires --api_key or FLASHTRACE_API_KEY/OPENAI_API_KEY.") + + attempted = 0 + skipped_format = 0 + judged_false = 0 + + indices = list(range(len(raw))) + if bool(args.shuffle): + import random + + rnd = random.Random(int(args.seed)) + rnd.shuffle(indices) + + kept_bar = tqdm(total=int(args.max_examples), desc="Kept (judge=True)", position=1, leave=False) + for loop_idx in tqdm(indices, total=len(indices), desc="Resampling"): + if kept >= int(args.max_examples): + break + + total += 1 + item = raw[loop_idx] + if not isinstance(item, dict): + skipped_parse += 1 + continue + + question = str(item.get("question") or "") + answer = str(item.get("answer") or "") + if not question.strip(): + skipped_empty_q += 1 + continue + if not answer.strip(): + skipped_empty_a += 1 + continue + + parsed = _split_gsm8k_answer(answer) + if parsed is None: + skipped_parse += 1 + continue + _ref_thinking, reference_answer = parsed + + attempted += 1 + gen_messages = build_gen_messages(question.strip()) + + # Step 1: generation + for attempt in range(int(args.retries) + 1): + try: + generation = call_chat_api( + str(args.api_base), + str(api_key), + str(args.generator_model), + gen_messages, + timeout=int(args.api_timeout), + max_tokens=int(args.api_max_tokens), + temperature=float(args.api_temperature), + cache_ttl=int(args.api_cache_ttl), + cache_namespace=str(args.api_cache_namespace) if args.api_cache_namespace else None, + rate_limit_delay=float(args.rate_limit_delay) if args.rate_limit_delay is not None else None, + ) + break + except RateLimitError as e: + if attempt >= int(args.retries): + raise + time.sleep(float(e.wait_seconds)) + except Exception: # noqa: BLE001 + if attempt >= int(args.retries): + raise + time.sleep(float(args.retry_delay)) + if float(args.request_interval) > 0: + time.sleep(float(args.request_interval)) + + parsed_gen = split_boxed_generation(generation) + if not parsed_gen: + skipped_format += 1 + print(f"[attempt={attempted}] skipped=format") + continue + + thinking_text, _boxed_segment, boxed_answer = parsed_gen + judge_messages = build_judge_messages(reference_answer, boxed_answer) + + ok = False + judge_resp = "" + for attempt in range(int(args.retries) + 1): + try: + judge_resp = call_chat_api( + str(args.api_base), + str(api_key), + str(args.judge_model), + judge_messages, + timeout=int(args.api_timeout), + max_tokens=64, + temperature=0.0, + cache_ttl=int(args.api_cache_ttl), + cache_namespace=str(args.api_cache_namespace) if args.api_cache_namespace else None, + rate_limit_delay=float(args.rate_limit_delay) if args.rate_limit_delay is not None else None, + ) + ok = parse_bool(judge_resp) + break + except RateLimitError as e: + if attempt >= int(args.retries): + raise + time.sleep(float(e.wait_seconds)) + except Exception: # noqa: BLE001 + if attempt >= int(args.retries): + raise + time.sleep(float(args.retry_delay)) + if float(args.judge_interval) > 0: + time.sleep(float(args.judge_interval)) + + if not ok: + judged_false += 1 + print(f"[attempt={attempted}] judge=filtered") + continue + + ex = _build_resampled_example( + question=question, + raw_answer=answer, + reference_answer=reference_answer, + generation=generation, + tokenizer=tokenizer, + example_idx=int(loop_idx), + source_path=str(in_path), + judge_response=judge_resp, + generator_model=str(args.generator_model), + judge_model=str(args.judge_model), + ) + if ex is None: + skipped_span += 1 + print(f"[attempt={attempted}] skipped=span") + continue + + examples.append(ex) + kept += 1 + kept_bar.update(1) + print(f"[attempt={attempted}] judge=kept") + + kept_bar.close() + + written = _write_jsonl(out_path, examples=examples) + if written != kept: + raise SystemExit(f"Internal error: written={written} != kept={kept}") + + print( + json.dumps( + { + "in_json": str(in_path), + "out_jsonl": str(out_path), + "tokenizer_model": args.tokenizer_model, + "mode": str(args.mode), + "source_total": int(source_total), + "visited": total, + "kept": kept, + "skipped_empty_question": skipped_empty_q, + "skipped_empty_answer": skipped_empty_a, + "skipped_parse": skipped_parse, + "skipped_span": skipped_span, + "attempted": attempted, + "skipped_format": skipped_format, + "judged_false": judged_false, + "max_examples": int(args.max_examples) if str(args.mode) == "resample" else None, + "api_base": str(args.api_base) if str(args.mode) == "resample" else None, + "generator_model": str(args.generator_model) if str(args.mode) == "resample" else None, + "judge_model": str(args.judge_model) if str(args.mode) == "resample" else None, + }, + ensure_ascii=False, + indent=2, + ) + ) + + +if __name__ == "__main__": + main() diff --git a/exp/exp2/migrate_indices_to_explain_token_span.py b/exp/exp2/migrate_indices_to_explain_token_span.py new file mode 100644 index 0000000000000000000000000000000000000000..2c7ba14fe8b71a3cad3959519e31ad2b54e507ee --- /dev/null +++ b/exp/exp2/migrate_indices_to_explain_token_span.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +"""Migrate exp2 cached JSONL to token-span `indices_to_explain`. + +This converts legacy caches that used sentence indices (e.g. `[-2]`) into the +token-span format: + + indices_to_explain = [start_tok, end_tok] + +Where the span points to the boxed-inner (final answer) token span in `target` +under `tokenizer(target, add_special_tokens=False)`. + +Rule: +1) If `sink_span` exists and looks valid -> copy it to `indices_to_explain` +2) Else try to recompute spans from `target` + `metadata.boxed_answer` using + `exp/exp2/dataset_utils.attach_spans_from_answer` +""" + +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path +from typing import Any, Dict, Optional + +from transformers import AutoTokenizer + + +def _ensure_repo_root_on_path() -> None: + repo_root = Path(__file__).resolve().parents[2] + if str(repo_root) not in sys.path: + sys.path.insert(0, str(repo_root)) + + +def _is_token_span(span: Any) -> bool: + return isinstance(span, list) and len(span) == 2 and all(isinstance(x, int) for x in span) + + +def _load_tokenizer(tokenizer_model: str): + tok_path = Path(tokenizer_model) + if tok_path.exists(): + return AutoTokenizer.from_pretrained(tok_path.as_posix(), local_files_only=True) + return AutoTokenizer.from_pretrained(tokenizer_model) + + +def _migrate_obj(obj: Dict[str, Any], tokenizer) -> tuple[Dict[str, Any], bool]: + sink_span = obj.get("sink_span") + if _is_token_span(sink_span): + obj["indices_to_explain"] = sink_span + return obj, True + + _ensure_repo_root_on_path() + from exp.exp2.dataset_utils import CachedExample, attach_spans_from_answer # noqa: E402 + + example = CachedExample( + prompt=obj.get("prompt") or "", + target=obj.get("target"), + indices_to_explain=obj.get("indices_to_explain"), + attr_mask_indices=obj.get("attr_mask_indices"), + sink_span=obj.get("sink_span"), + thinking_span=obj.get("thinking_span"), + metadata=obj.get("metadata") or {}, + ) + answer_text = (example.metadata.get("boxed_answer") or "").strip() or None + migrated = attach_spans_from_answer(example, tokenizer, answer_text) + if not _is_token_span(migrated.sink_span): + return obj, False + + obj["sink_span"] = migrated.sink_span + obj["thinking_span"] = migrated.thinking_span + obj["indices_to_explain"] = migrated.sink_span + obj["metadata"] = migrated.metadata + return obj, True + + +def main() -> None: + ap = argparse.ArgumentParser() + ap.add_argument("--in_jsonl", type=str, required=True) + ap.add_argument("--out_jsonl", type=str, required=True) + ap.add_argument("--tokenizer_model", type=str, required=True) + ap.add_argument("--strict", action="store_true", help="Fail on any line that cannot be migrated.") + args = ap.parse_args() + + tokenizer = _load_tokenizer(args.tokenizer_model) + + in_path = Path(args.in_jsonl) + out_path = Path(args.out_jsonl) + + try: + same_path = in_path.resolve() == out_path.resolve() + except FileNotFoundError: + same_path = False + + tmp_out_path = out_path + if same_path: + tmp_out_path = out_path.with_name(out_path.name + ".tmp") + if tmp_out_path.exists(): + tmp_out_path.unlink() + + tmp_out_path.parent.mkdir(parents=True, exist_ok=True) + + total = 0 + migrated_ok = 0 + bad = 0 + + with in_path.open("r", encoding="utf-8") as fin, tmp_out_path.open("w", encoding="utf-8") as fout: + for line_no, line in enumerate(fin, start=1): + if not line.strip(): + continue + total += 1 + obj: Dict[str, Any] = json.loads(line) + new_obj, ok = _migrate_obj(obj, tokenizer) + if ok: + migrated_ok += 1 + else: + bad += 1 + if args.strict: + raise RuntimeError(f"cannot migrate line {line_no}: cannot resolve sink_span token span") + fout.write(json.dumps(new_obj, ensure_ascii=False) + "\n") + + if same_path: + tmp_out_path.replace(out_path) + print(f"[done] total={total} migrated_ok={migrated_ok} bad={bad} wrote={out_path} (in-place)") + else: + print(f"[done] total={total} migrated_ok={migrated_ok} bad={bad} wrote={out_path}") + + +if __name__ == "__main__": + main() diff --git a/exp/exp2/out.log b/exp/exp2/out.log new file mode 100644 index 0000000000000000000000000000000000000000..9bd68c485c6547f61c0295e97db643f88e99cb2c --- /dev/null +++ b/exp/exp2/out.log @@ -0,0 +1,102 @@ +[1/500] judge=kept +[2/500] judge=kept +[3/500] judge=kept +[4/500] judge=kept +[5/500] judge=kept +[6/500] judge=kept +[7/500] judge=kept +[8/500] judge=kept +[9/500] judge=kept +[10/500] judge=kept +[11/500] judge=kept +[12/500] judge=kept +[13/500] judge=kept +[14/500] judge=kept +[15/500] judge=kept +[16/500] judge=kept +[17/500] judge=kept +[18/500] judge=kept +[19/500] judge=kept +[20/500] judge=kept +[21/500] judge=kept +[22/500] judge=kept +[23/500] judge=kept +[24/500] judge=kept +[25/500] judge=kept +[26/500] judge=kept +[27/500] judge=kept +[28/500] judge=kept +[29/500] judge=kept +[30/500] judge=kept +[31/500] judge=kept +[32/500] judge=kept +[33/500] judge=kept +[34/500] judge=kept +[35/500] judge=kept +[36/500] judge=kept +[37/500] judge=kept +[38/500] judge=kept +[39/500] judge=kept +[40/500] judge=kept +[41/500] judge=kept +[42/500] judge=kept +[43/500] judge=kept +[44/500] judge=kept +[45/500] judge=kept +[46/500] judge=kept +[47/500] judge=kept +[48/500] judge=kept +[49/500] judge=kept +[50/500] judge=kept +[51/500] judge=kept +[52/500] judge=kept +[53/500] judge=kept +[54/500] judge=kept +[55/500] judge=kept +[56/500] judge=kept +[57/500] judge=kept +[58/500] judge=kept +[59/500] judge=kept +[60/500] judge=kept +[61/500] judge=kept +[62/500] judge=kept +[63/500] skipped=format +[64/500] judge=kept +[65/500] judge=kept +[66/500] judge=kept +[67/500] judge=kept +[68/500] judge=kept +[69/500] judge=kept +[70/500] judge=kept +[71/500] judge=kept +[72/500] judge=kept +[73/500] judge=kept +[74/500] judge=kept +[75/500] judge=kept +[76/500] judge=kept +[77/500] judge=kept +[78/500] judge=kept +[79/500] judge=kept +[80/500] judge=kept +[81/500] judge=kept +[82/500] judge=kept +[83/500] judge=kept +[84/500] judge=kept +[85/500] judge=kept +[86/500] judge=kept +[87/500] judge=kept +[88/500] judge=kept +[89/500] judge=kept +[90/500] judge=kept +[91/500] judge=kept +[92/500] judge=kept +[93/500] judge=kept +[94/500] judge=kept +[95/500] judge=kept +[96/500] judge=kept +[97/500] judge=kept +[98/500] judge=kept +[99/500] judge=kept +[100/500] judge=kept +[101/500] judge=kept +Kept 100 / target 100 (attempted 101 / 500) -> exp/exp2/data/data/ruler_multihop/1024/vt_h10_c1/validation.jsonl.jsonl diff --git a/exp/exp2/run_exp.py b/exp/exp2/run_exp.py new file mode 100644 index 0000000000000000000000000000000000000000..927d83488d0a11953f4c7024f8c44f5111859355 --- /dev/null +++ b/exp/exp2/run_exp.py @@ -0,0 +1,1296 @@ +#!/usr/bin/env python3 +""" +Experiment 2 runner: token-level faithfulness (generation perturbation). + +AT2 is omitted. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +import sys +from itertools import islice +import math +import time +from pathlib import Path +from typing import Any, Dict, List, Optional, Tuple + +# Early CUDA mask handling: set CUDA_VISIBLE_DEVICES before importing torch. +def _early_set_cuda_visible_devices(): + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("--cuda", type=str, default=None) + # parse_known_args keeps the full argv for later parsing by the main parser + args, _ = parser.parse_known_args(sys.argv[1:]) + if args.cuda and "," in args.cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = args.cuda + + +_early_set_cuda_visible_devices() + +import numpy as np +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer, utils + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from pathlib import Path + +# ensure repo root on path +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + +import llm_attr +import llm_attr_eval +from attribution_datasets import AttributionExample +from exp.exp2 import dataset_utils as ds_utils + +utils.logging.set_verbosity_error() + + +def _sha1_text(text: str) -> str: + return hashlib.sha1(text.encode("utf-8")).hexdigest() + + +def _infer_attnlrp_spans_from_hops( + raw_attributions: Any, + *, + gen_len: int, +) -> Tuple[Tuple[int, int], Tuple[int, int]]: + if not raw_attributions: + return (0, max(0, gen_len - 1)), (0, max(0, gen_len - 1)) + sink_span = tuple(int(x) for x in raw_attributions[0].sink_range) + if len(raw_attributions) >= 2: + thinking_span = tuple(int(x) for x in raw_attributions[1].sink_range) + else: + thinking_span = sink_span + return sink_span, thinking_span + + +def _build_hop_trace_payload( + attr_func: str, + attr: Any, + *, + indices_to_explain: List[int], +) -> Optional[Dict[str, np.ndarray]]: + """Extract per-hop vectors (postprocessed) and minimal span metadata.""" + prompt_len = int(len(getattr(attr, "prompt_tokens", []) or [])) + gen_len = int(len(getattr(attr, "generation_tokens", []) or [])) + total_len = prompt_len + gen_len + if total_len <= 0: + return None + + hop_vectors: List[torch.Tensor] = [] + sink_span_gen: Optional[Tuple[int, int]] = None + thinking_span_gen: Optional[Tuple[int, int]] = None + attnlrp_neg_handling: str = "" + attnlrp_norm_mode: str = "" + attnlrp_ratio_enabled: int = -1 + + # IFR multi-hop variants expose projected hop vectors via metadata["ifr"]["per_hop_projected"]. + ifr_meta = (getattr(attr, "metadata", None) or {}).get("ifr") or {} + ifr_per_hop = ifr_meta.get("per_hop_projected") or [] + + if ifr_per_hop: + hop_vectors = [torch.as_tensor(v, dtype=torch.float32) for v in ifr_per_hop] + sink_span_gen = ifr_meta.get("sink_span_generation") + thinking_span_gen = ifr_meta.get("thinking_span_generation") + if sink_span_gen is not None: + sink_span_gen = tuple(int(x) for x in sink_span_gen) + if thinking_span_gen is not None: + thinking_span_gen = tuple(int(x) for x in thinking_span_gen) + + elif attr_func in ("ft_attnlrp", "attnlrp_aggregated_multi_hop"): + meta = getattr(attr, "metadata", None) or {} + attnlrp_neg_handling = str(meta.get("neg_handling") or "") + attnlrp_norm_mode = str(meta.get("norm_mode") or "") + if meta.get("ratio_enabled") is not None: + attnlrp_ratio_enabled = int(bool(meta.get("ratio_enabled"))) + multi_hop = meta.get("multi_hop_result") + if multi_hop is None: + return None + raw_attributions = getattr(multi_hop, "raw_attributions", None) or [] + if not raw_attributions: + return None + hop_vectors = [ + torch.as_tensor(getattr(hop, "token_importance_total"), dtype=torch.float32) + for hop in raw_attributions + ] + sink_span_gen, thinking_span_gen = _infer_attnlrp_spans_from_hops(raw_attributions, gen_len=gen_len) + sink_override = meta.get("sink_span") + thinking_override = meta.get("thinking_span") + if sink_override is not None: + sink_span_gen = tuple(int(x) for x in sink_override) + if thinking_override is not None: + thinking_span_gen = tuple(int(x) for x in thinking_override) + + else: + return None + + if sink_span_gen is None: + sink_span_gen = (0, max(0, gen_len - 1)) + if thinking_span_gen is None: + thinking_span_gen = sink_span_gen + + stacked = torch.stack([v.reshape(-1) for v in hop_vectors], dim=0) + if stacked.shape[1] != total_len: + raise ValueError( + f"Hop vector length mismatch for {attr_func}: expected T={total_len}, got {stacked.shape[1]}." + ) + + return { + "vh": stacked.detach().cpu().numpy().astype(np.float32, copy=False), + "prompt_len": np.asarray(prompt_len, dtype=np.int64), + "gen_len": np.asarray(gen_len, dtype=np.int64), + "sink_span_gen": np.asarray(sink_span_gen, dtype=np.int64), + "thinking_span_gen": np.asarray(thinking_span_gen, dtype=np.int64), + "indices_to_explain_gen": np.asarray(indices_to_explain, dtype=np.int64), + "attnlrp_neg_handling": np.asarray(attnlrp_neg_handling, dtype="U16"), + "attnlrp_norm_mode": np.asarray(attnlrp_norm_mode, dtype="U16"), + "attnlrp_ratio_enabled": np.asarray(attnlrp_ratio_enabled, dtype=np.int64), + } + + +def _write_hop_trace( + trace_dir: Path, + *, + example_idx: int, + attr_func: str, + prompt: str, + target: Optional[str], + payload: Dict[str, np.ndarray], + manifest_handle, +) -> None: + trace_dir.mkdir(parents=True, exist_ok=True) + npz_name = f"ex_{example_idx:06d}.npz" + npz_path = trace_dir / npz_name + np.savez_compressed(npz_path, **payload) + + record = { + "example_idx": int(example_idx), + "attr_func": attr_func, + "file": npz_name, + "prompt_sha1": _sha1_text(prompt), + "target_sha1": _sha1_text(target) if target is not None else None, + "prompt_len": int(payload["prompt_len"].item()), + "gen_len": int(payload["gen_len"].item()), + "n_hops_plus_one": int(payload["vh"].shape[0]), + "total_len": int(payload["vh"].shape[1]), + "sink_span_gen": payload["sink_span_gen"].tolist(), + "thinking_span_gen": payload["thinking_span_gen"].tolist(), + "indices_to_explain_gen": payload["indices_to_explain_gen"].tolist(), + "attnlrp_neg_handling": str(payload["attnlrp_neg_handling"].item()), + "attnlrp_norm_mode": str(payload["attnlrp_norm_mode"].item()), + "attnlrp_ratio_enabled": int(payload["attnlrp_ratio_enabled"].item()), + } + manifest_handle.write(json.dumps(record, ensure_ascii=False) + "\n") + manifest_handle.flush() + + +def _parse_modes(mode_args: Any) -> List[str]: + """Parse --mode which may be provided as multiple args and/or comma-separated.""" + if mode_args is None: + raw_parts: List[str] = [] + elif isinstance(mode_args, str): + raw_parts = [mode_args] + else: + raw_parts = [str(x) for x in mode_args] + + modes: List[str] = [] + for chunk in raw_parts: + for part in str(chunk).split(","): + m = part.strip() + if m: + modes.append(m) + + # Default to faithfulness_gen for backward compatibility. + if not modes: + modes = ["faithfulness_gen"] + + allowed = {"faithfulness_gen", "recovery_ruler"} + seen: set[str] = set() + unique: List[str] = [] + for m in modes: + if m not in seen: + unique.append(m) + seen.add(m) + + unknown = [m for m in unique if m not in allowed] + if unknown: + raise SystemExit(f"Unsupported --mode value(s): {unknown}. Allowed: {sorted(allowed)}.") + + return unique + + +def _trace_run_tag( + testing_dict: Dict[str, Any], + *, + modes: List[str], + total: int, +) -> str: + attr_func = str(testing_dict.get("attr_func") or "attr") + parts = [attr_func] + + if attr_func in ( + "ifr_multi_hop", + "ifr_in_all_gen", + "ifr_multi_hop_stop_words", + "ifr_multi_hop_both", + "ifr_multi_hop_split_hop", + "ft_attnlrp", + "attnlrp_aggregated_multi_hop", + ): + parts.append(f"n{int(testing_dict.get('n_hops', 0))}") + + if attr_func in ("attnlrp", "ft_attnlrp", "attnlrp_aggregated_multi_hop"): + parts.append(f"neg{str(testing_dict.get('attnlrp_neg_handling', ''))}") + parts.append(f"norm{str(testing_dict.get('attnlrp_norm_mode', ''))}") + + if modes: + parts.append("m" + "+".join(modes)) + + parts.append(f"{int(total)}ex") + return "_".join(parts) + + +def _token_importance_vector(attr: torch.Tensor) -> np.ndarray: + """Return token importance vector w = sum_rows(attr) in shape [P+G].""" + w = torch.nan_to_num(attr.sum(0).to(dtype=torch.float32), nan=0.0).clamp(min=0.0) + return w.detach().cpu().numpy().astype(np.float32, copy=False) + + +def _build_sample_trace_payload( + example: ds_utils.CachedExample, + *, + attr_list: List[torch.Tensor], + prompt_len: int, + user_prompt_indices: Optional[List[int]], + keep_prompt_token_indices: Optional[List[int]], + gold_prompt_token_indices: Optional[List[int]], + hop_payload: Optional[Dict[str, np.ndarray]], + faithfulness_scores: Optional[np.ndarray], + recovery_scores: Optional[np.ndarray], + time_attr_s: Optional[float], + time_faith_s: Optional[float], + time_recovery_s: Optional[float], +) -> Dict[str, np.ndarray]: + seq_attr, row_attr, rec_attr = attr_list + gen_len = int(seq_attr.shape[0]) + + v_seq_all = _token_importance_vector(seq_attr) + v_row_all = _token_importance_vector(row_attr) + v_rec_all = _token_importance_vector(rec_attr) + + payload: Dict[str, np.ndarray] = { + "v_seq_all": v_seq_all, + "v_row_all": v_row_all, + "v_rec_all": v_rec_all, + "v_seq_prompt": v_seq_all[:prompt_len], + "v_row_prompt": v_row_all[:prompt_len], + "v_rec_prompt": v_rec_all[:prompt_len], + "prompt_len": np.asarray(int(prompt_len), dtype=np.int64), + "gen_len": np.asarray(int(gen_len), dtype=np.int64), + "indices_to_explain_gen": np.asarray(list(example.indices_to_explain or []), dtype=np.int64), + } + + if example.sink_span is not None: + payload["sink_span_gen"] = np.asarray(list(example.sink_span), dtype=np.int64) + if example.thinking_span is not None: + payload["thinking_span_gen"] = np.asarray(list(example.thinking_span), dtype=np.int64) + + if user_prompt_indices is not None: + payload["user_prompt_indices"] = np.asarray(list(user_prompt_indices), dtype=np.int64) + if keep_prompt_token_indices is not None: + payload["keep_prompt_token_indices"] = np.asarray(list(keep_prompt_token_indices), dtype=np.int64) + if gold_prompt_token_indices is not None: + payload["gold_prompt_token_indices"] = np.asarray(list(gold_prompt_token_indices), dtype=np.int64) + + if faithfulness_scores is not None: + payload["faithfulness_scores"] = np.asarray(faithfulness_scores, dtype=np.float64) + if recovery_scores is not None: + payload["recovery_scores"] = np.asarray(recovery_scores, dtype=np.float64) + + if time_attr_s is not None: + payload["time_attr_s"] = np.asarray(float(time_attr_s), dtype=np.float64) + if time_faith_s is not None: + payload["time_faith_s"] = np.asarray(float(time_faith_s), dtype=np.float64) + if time_recovery_s is not None: + payload["time_recovery_s"] = np.asarray(float(time_recovery_s), dtype=np.float64) + + if hop_payload is not None: + for k, v in hop_payload.items(): + if k in payload: + continue + payload[k] = v + + return payload + + +def _write_sample_trace( + trace_dir: Path, + *, + example_idx: int, + attr_func: str, + prompt: str, + target: Optional[str], + payload: Dict[str, np.ndarray], + manifest_handle, + recovery_skipped_reason: Optional[str], +) -> None: + trace_dir.mkdir(parents=True, exist_ok=True) + npz_name = f"ex_{example_idx:06d}.npz" + npz_path = trace_dir / npz_name + np.savez_compressed(npz_path, **payload) + + prompt_len = int(np.asarray(payload.get("prompt_len", 0)).item()) + gen_len = int(np.asarray(payload.get("gen_len", 0)).item()) + record: Dict[str, Any] = { + "example_idx": int(example_idx), + "attr_func": attr_func, + "file": npz_name, + "prompt_sha1": _sha1_text(prompt), + "target_sha1": _sha1_text(target) if target is not None else None, + "prompt_len": prompt_len, + "gen_len": gen_len, + "indices_to_explain_gen": payload.get("indices_to_explain_gen").tolist() + if payload.get("indices_to_explain_gen") is not None + else None, + "sink_span_gen": payload.get("sink_span_gen").tolist() if payload.get("sink_span_gen") is not None else None, + "thinking_span_gen": payload.get("thinking_span_gen").tolist() + if payload.get("thinking_span_gen") is not None + else None, + "faithfulness_scores": payload.get("faithfulness_scores").tolist() + if payload.get("faithfulness_scores") is not None + else None, + "recovery_scores": payload.get("recovery_scores").tolist() if payload.get("recovery_scores") is not None else None, + "recovery_skipped_reason": recovery_skipped_reason, + "time_attr_s": float(np.asarray(payload.get("time_attr_s")).item()) if payload.get("time_attr_s") is not None else None, + "time_faith_s": float(np.asarray(payload.get("time_faith_s")).item()) if payload.get("time_faith_s") is not None else None, + "time_recovery_s": float(np.asarray(payload.get("time_recovery_s")).item()) + if payload.get("time_recovery_s") is not None + else None, + } + + # Derived, sample-level bookkeeping (token lengths and per-sample MAS/RISE). + record["input_len"] = int(prompt_len) + + sink_span = record.get("sink_span_gen") + if isinstance(sink_span, list) and len(sink_span) == 2: + try: + start = int(sink_span[0]) + end = int(sink_span[1]) + record["output_len"] = (end - start + 1) if end >= start else None + except Exception: + record["output_len"] = None + else: + record["output_len"] = None + + thinking_span = record.get("thinking_span_gen") + if isinstance(thinking_span, list) and len(thinking_span) == 2: + try: + start = int(thinking_span[0]) + end = int(thinking_span[1]) + record["cot_len"] = (end - start + 1) if end >= start else None + except Exception: + record["cot_len"] = None + else: + record["cot_len"] = None + + record["rise_seq"] = None + record["mas_seq"] = None + record["rise_row"] = None + record["mas_row"] = None + record["rise_rec"] = None + record["mas_rec"] = None + faith = record.get("faithfulness_scores") + if isinstance(faith, list) and len(faith) == 3: + try: + record["rise_seq"] = float(faith[0][0]) + record["mas_seq"] = float(faith[0][1]) + record["rise_row"] = float(faith[1][0]) + record["mas_row"] = float(faith[1][1]) + record["rise_rec"] = float(faith[2][0]) + record["mas_rec"] = float(faith[2][1]) + except Exception: + pass + + if payload.get("vh") is not None: + vh = payload["vh"] + record["n_hops_plus_one"] = int(vh.shape[0]) + record["total_len"] = int(vh.shape[1]) + record["attnlrp_neg_handling"] = str(payload.get("attnlrp_neg_handling").item()) if payload.get("attnlrp_neg_handling") is not None else "" + record["attnlrp_norm_mode"] = str(payload.get("attnlrp_norm_mode").item()) if payload.get("attnlrp_norm_mode") is not None else "" + record["attnlrp_ratio_enabled"] = int(payload.get("attnlrp_ratio_enabled").item()) if payload.get("attnlrp_ratio_enabled") is not None else -1 + + manifest_handle.write(json.dumps(record, ensure_ascii=False) + "\n") + manifest_handle.flush() + + +def _compute_faithfulness_scores( + testing_dict: Dict[str, Any], + *, + attr_list: List[torch.Tensor], + prompt_len: int, + prompt: str, + generation: str, + llm_evaluator: llm_attr_eval.LLMAttributionEvaluator, + user_prompt_indices: Optional[List[int]], + keep_prompt_token_indices: Optional[List[int]], +) -> np.ndarray: + attr_func = str(testing_dict.get("attr_func") or "") + results: List[Tuple[float, float, float]] = [] + for attr in attr_list: + attr_prompt = attr[:, :prompt_len] + if attr_func in ("ifr_multi_hop_stop_words", "ifr_multi_hop_both") and keep_prompt_token_indices is not None: + import ft_ifr_improve + + scores = ft_ifr_improve.faithfulness_test_skip_tokens( + llm_evaluator, + attr_prompt, + prompt, + generation, + keep_prompt_token_indices=keep_prompt_token_indices, + user_prompt_indices=user_prompt_indices, + ) + elif user_prompt_indices is not None: + scores = _faithfulness_test_with_user_prompt_indices( + llm_evaluator, + attr_prompt, + prompt, + generation, + user_prompt_indices=user_prompt_indices, + ) + else: + scores = llm_evaluator.faithfulness_test(attr_prompt, prompt, generation) + results.append(scores) + return np.asarray(results, dtype=np.float64) + + +def _compute_recovery_scores( + testing_dict: Dict[str, Any], + *, + attr_list: List[torch.Tensor], + prompt_len: int, + gold_prompt_token_indices: List[int], + llm_evaluator: llm_attr_eval.LLMAttributionEvaluator, + keep_prompt_token_indices: Optional[List[int]], +) -> Tuple[Optional[np.ndarray], Optional[str]]: + attr_func = str(testing_dict.get("attr_func") or "") + + if prompt_len <= 0: + return None, "empty_prompt_len" + + gold_prompt = [int(x) for x in (gold_prompt_token_indices or [])] + if not gold_prompt: + return None, "empty_gold_prompt" + + if attr_func in ("ifr_multi_hop_stop_words", "ifr_multi_hop_both") and keep_prompt_token_indices is not None: + import ft_ifr_improve + + keep_set = {int(x) for x in keep_prompt_token_indices} + gold_filtered = [idx for idx in gold_prompt if int(idx) in keep_set] + if not gold_filtered: + return None, "empty_gold_after_keep_filter" + + scores = [ + ft_ifr_improve.evaluate_attr_recovery_skip_tokens( + attr[:, :prompt_len], + keep_prompt_token_indices=keep_prompt_token_indices, + gold_prompt_token_indices=gold_prompt, + top_fraction=0.1, + ) + for attr in attr_list + ] + else: + scores = [ + llm_evaluator.evaluate_attr_recovery( + attr, + prompt_len=prompt_len, + gold_prompt_token_indices=gold_prompt, + top_fraction=0.1, + ) + for attr in attr_list + ] + + return np.asarray(scores, dtype=np.float64), None + + +def evaluate_dataset_multi( + args, + dataset_name: str, + examples: List[ds_utils.CachedExample], + testing_dict: Dict[str, Any], + *, + modes: List[str], +) -> Dict[str, Any]: + tokenizer = testing_dict["tokenizer"] + llm_evaluator = llm_attr_eval.LLMAttributionEvaluator(testing_dict["model"], tokenizer) + + want_faith = "faithfulness_gen" in modes + want_recovery = "recovery_ruler" in modes + + faith_results: List[np.ndarray] = [] + faith_durations: List[float] = [] + + recovery_results: List[np.ndarray] = [] + recovery_attr_durations: List[float] = [] + recovery_skipped = 0 + + total = min(len(examples), args.num_examples) + iterator = islice(examples, total) + + save_traces = bool(getattr(args, "save_hop_traces", False)) + manifest_handle = None + trace_dir: Optional[Path] = None + if save_traces: + model_tag = str(testing_dict.get("model_tag", "model")) + run_tag = _trace_run_tag(testing_dict, modes=modes, total=total) + trace_dir = Path(args.output_root) / "traces" / dataset_name / model_tag / run_tag + trace_dir.mkdir(parents=True, exist_ok=True) + manifest_handle = open(trace_dir / "manifest.jsonl", "w", encoding="utf-8") + + try: + for example_idx, ex in enumerate(iterator): + if want_recovery: + needle_spans = (ex.metadata or {}).get("needle_spans") + if not isinstance(needle_spans, list) or not needle_spans: + raise SystemExit( + "recovery_ruler requires RULER samples with metadata.needle_spans; " + f"dataset={dataset_name} has missing/empty needle_spans." + ) + if ex.target is None: + raise SystemExit( + "recovery_ruler requires cached targets (CoT+answer) so row/rec attribution is well-defined. " + f"dataset={dataset_name} has target=None; run exp/exp2/sample_and_filter.py first." + ) + + # Determine generation/target once. + target = ex.target + if target is None: + generation, full_output = llm_evaluator.response(ex.prompt) + target = generation + response_len = len(tokenizer(full_output).input_ids) + else: + response_len = len(tokenizer(llm_evaluator.format_prompt(" " + ex.prompt) + target).input_ids) + + testing_dict["batch_size"] = max(1, math.floor((testing_dict["max_input_len"] - 100) / max(1, response_len))) + + gold_prompt: Optional[List[int]] = None + if want_recovery: + gold_prompt = ds_utils.ruler_gold_prompt_token_indices(ex, tokenizer) + + if want_recovery and not want_faith and not save_traces: + # Preserve recovery-only fast path when not saving traces: skip samples with empty gold. + if not gold_prompt: + recovery_skipped += 1 + continue + + time_attr_s = None + time_faith_s = None + time_recovery_s = None + + t0 = time.perf_counter() + attr_list, hop_payload, user_prompt_indices, keep_prompt_token_indices = run_attribution(testing_dict, ex, target) + time_attr_s = time.perf_counter() - t0 + + seq_attr = attr_list[0] + prompt_len = int(seq_attr.shape[1] - seq_attr.shape[0]) # cols=(P+G), rows=G + + if want_recovery and gold_prompt: + recovery_attr_durations.append(float(time_attr_s)) + + faith_scores = None + if want_faith: + t1 = time.perf_counter() + faith_scores = _compute_faithfulness_scores( + testing_dict, + attr_list=attr_list, + prompt_len=prompt_len, + prompt=ex.prompt, + generation=target, + llm_evaluator=llm_evaluator, + user_prompt_indices=user_prompt_indices, + keep_prompt_token_indices=keep_prompt_token_indices, + ) + time_faith_s = time.perf_counter() - t1 + faith_results.append(faith_scores) + faith_durations.append(float(time_attr_s)) + + recovery_scores = None + recovery_skip_reason = None + if want_recovery: + if not gold_prompt: + recovery_skip_reason = "empty_gold_prompt" + recovery_skipped += 1 + else: + t2 = time.perf_counter() + recovery_scores, recovery_skip_reason = _compute_recovery_scores( + testing_dict, + attr_list=attr_list, + prompt_len=prompt_len, + gold_prompt_token_indices=gold_prompt, + llm_evaluator=llm_evaluator, + keep_prompt_token_indices=keep_prompt_token_indices, + ) + time_recovery_s = time.perf_counter() - t2 + if recovery_scores is None: + recovery_skipped += 1 + else: + recovery_results.append(recovery_scores) + + if manifest_handle is not None and trace_dir is not None: + try: + payload = _build_sample_trace_payload( + ex, + attr_list=attr_list, + prompt_len=prompt_len, + user_prompt_indices=user_prompt_indices, + keep_prompt_token_indices=keep_prompt_token_indices, + gold_prompt_token_indices=gold_prompt, + hop_payload=hop_payload, + faithfulness_scores=faith_scores, + recovery_scores=recovery_scores, + time_attr_s=time_attr_s, + time_faith_s=time_faith_s, + time_recovery_s=time_recovery_s, + ) + _write_sample_trace( + trace_dir, + example_idx=example_idx, + attr_func=str(testing_dict.get("attr_func") or ""), + prompt=ex.prompt, + target=target, + payload=payload, + manifest_handle=manifest_handle, + recovery_skipped_reason=recovery_skip_reason, + ) + except Exception as exc: + print(f"[warn] sample trace save failed for {testing_dict.get('attr_func')} ex={example_idx}: {exc}") + finally: + if manifest_handle is not None: + try: + manifest_handle.close() + except Exception: + pass + + out: Dict[str, Any] = {} + if want_faith: + if not faith_results: + out["faithfulness"] = None + else: + scores = np.stack(faith_results, axis=0) # [N, 3, 3] + out["faithfulness"] = { + "mean": scores.mean(0), + "std": scores.std(0), + "avg_time": float(np.mean(faith_durations)) if faith_durations else 0.0, + } + if want_recovery: + if not recovery_results: + out["recovery"] = None + else: + scores = np.stack(recovery_results, axis=0) # [N, 3] + out["recovery"] = { + "mean": scores.mean(0), + "std": scores.std(0), + "avg_time": float(np.mean(recovery_attr_durations)) if recovery_attr_durations else 0.0, + "used": int(scores.shape[0]), + "skipped": int(recovery_skipped), + } + + return out + + +def _faithfulness_test_with_user_prompt_indices( + llm_evaluator: llm_attr_eval.LLMAttributionEvaluator, + attribution: torch.Tensor, + prompt: str, + generation: str, + *, + user_prompt_indices: List[int], + k: int = 20, ### control the MAS steps per sample +) -> Tuple[float, float, float]: + """Token-level MAS/RISE faithfulness via guided deletion in k perturbation steps using provided prompt indices. + + This mirrors llm_attr_eval.LLMAttributionEvaluator.faithfulness_test, but avoids + locating the user prompt span via token-id subsequence matching (which may fail + for some tokenizers due to non-compositional BPE merges at template boundaries). + """ + + def auc(arr: np.ndarray) -> float: + return (arr.sum() - arr[0] / 2 - arr[-1] / 2) / max(1, (arr.shape[0] - 1)) + + pad_token_id = llm_evaluator._ensure_pad_token_id() + + user_prompt = " " + prompt + formatted_prompt = llm_evaluator.format_prompt(user_prompt) + formatted_ids = llm_evaluator.tokenizer(formatted_prompt, return_tensors="pt", add_special_tokens=False).input_ids + + prompt_ids = formatted_ids.to(llm_evaluator.device) + prompt_ids_perturbed = prompt_ids.clone() + generation_ids = llm_evaluator.tokenizer( + generation + llm_evaluator.tokenizer.eos_token, + return_tensors="pt", + add_special_tokens=False, + ).input_ids.to(llm_evaluator.device) + + attr_cpu = attribution.detach().cpu() + w = attr_cpu.sum(0) + sorted_attr_indices = torch.argsort(w, descending=True) + attr_sum = float(w.sum().item()) + + P = int(w.numel()) + if len(user_prompt_indices) != P: + raise ValueError( + "user_prompt_indices length does not match prompt-side attribution length: " + f"indices P={len(user_prompt_indices)}, attr P={P}." + ) + if P == 0: + return 0.0, 0.0, 0.0 + + if max(user_prompt_indices) >= int(prompt_ids_perturbed.shape[1]): + raise ValueError("user_prompt_indices contains an out-of-bounds index for formatted prompt ids.") + + if P > 0: + steps = int(k) if k is not None else 0 + if steps <= 0: + steps = 1 + steps = min(steps, P) + else: + steps = 0 + + scores = np.zeros(steps + 1, dtype=np.float64) + density = np.zeros(steps + 1, dtype=np.float64) + + scores[0] = ( + llm_evaluator.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + ) + density[0] = 1.0 + + if attr_sum <= 0: + density = np.linspace(1.0, 0.0, steps + 1) + + base = P // steps + remainder = P % steps + start = 0 + for step in range(steps): + size = base + (1 if step < remainder else 0) + group = sorted_attr_indices[start : start + size] + start += size + + for idx in group: + j = int(idx.item()) + abs_pos = int(user_prompt_indices[j]) + prompt_ids_perturbed[0, abs_pos] = pad_token_id + scores[step + 1] = ( + llm_evaluator.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + ) + if attr_sum > 0: + dec = float(w.index_select(0, group).sum().item()) / attr_sum + density[step + 1] = density[step] - dec + + min_normalized_pred = 1.0 + normalized_model_response = scores.copy() + for i in range(len(scores)): + normalized_pred = (normalized_model_response[i] - scores[-1]) / (abs(scores[0] - scores[-1])) + normalized_pred = np.clip(normalized_pred, 0.0, 1.0) + min_normalized_pred = min(min_normalized_pred, normalized_pred) + normalized_model_response[i] = min_normalized_pred + + alignment_penalty = np.abs(normalized_model_response - density) + corrected_scores = normalized_model_response + alignment_penalty + corrected_scores = corrected_scores.clip(0.0, 1.0) + corrected_scores = (corrected_scores - np.min(corrected_scores)) / (np.max(corrected_scores) - np.min(corrected_scores)) + + if np.isnan(corrected_scores).any(): + corrected_scores = np.linspace(1.0, 0.0, len(scores)) + + return auc(normalized_model_response), auc(corrected_scores), auc(normalized_model_response + alignment_penalty) + + +def load_model(model_name: str, device: str): + model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map="auto" if device == "auto" else {"": int(device.split(":")[1])} if device.startswith("cuda:") else None, + torch_dtype=torch.float16, + attn_implementation="eager", + ) + tokenizer = AutoTokenizer.from_pretrained(model_name) + tokenizer.pad_token = tokenizer.eos_token + model.eval() + return model, tokenizer + + +def resolve_device(args) -> str: + if args.cuda is not None and "," in args.cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = args.cuda + return "auto" + if args.cuda is not None and args.cuda.strip(): + return f"cuda:{args.cuda}" if torch.cuda.is_available() else "cpu" + return f"cuda:{args.cuda_num}" if torch.cuda.is_available() else "cpu" + + +def run_attribution( + testing_dict, example: ds_utils.CachedExample, target: Optional[str] +) -> Tuple[List[torch.Tensor], Optional[Dict[str, np.ndarray]], Optional[List[int]]]: + model = testing_dict["model"] + tokenizer = testing_dict["tokenizer"] + attr_func = testing_dict["attr_func"] + + indices_to_explain = example.indices_to_explain + if not (isinstance(indices_to_explain, list) and len(indices_to_explain) == 2): + raise ValueError( + "exp2 requires token-span indices_to_explain=[start_tok,end_tok]. " + "Please re-sample or run exp/exp2/migrate_indices_to_explain_token_span.py on your cache." + ) + + llm_attributor = None + if "IG" in attr_func: + llm_attributor = llm_attr.LLMGradientAttribtion(model, tokenizer) + attr = llm_attributor.calculate_IG_per_generation( + example.prompt, + 20, + tokenizer.eos_token_id, + batch_size=testing_dict["batch_size"], + target=target, + ) + elif "perturbation" in attr_func: + if attr_func in ("perturbation_all_fast", "perturbation_CLP_fast", "perturbation_REAGENT_fast"): + import perturbation_fast + + llm_attributor = perturbation_fast.LLMPerturbationFastAttribution(model, tokenizer) + if attr_func == "perturbation_all_fast": + attr = llm_attributor.calculate_feature_ablation_segments( + example.prompt, + baseline=tokenizer.eos_token_id, + measure="log_loss", + target=target, + source_k=20, + ) + elif attr_func == "perturbation_CLP_fast": + attr = llm_attributor.calculate_feature_ablation_segments( + example.prompt, + baseline=tokenizer.eos_token_id, + measure="KL", + target=target, + source_k=20, + ) + else: + attr = llm_attributor.calculate_feature_ablation_segments_mlm( + example.prompt, + target=target, + source_k=20, + ) + else: + llm_attributor = llm_attr.LLMPerturbationAttribution(model, tokenizer) + if attr_func == "perturbation_all": + attr = llm_attributor.calculate_feature_ablation_sentences( + example.prompt, baseline=tokenizer.eos_token_id, measure="log_loss", target=target + ) + elif attr_func == "perturbation_CLP": + attr = llm_attributor.calculate_feature_ablation_sentences( + example.prompt, baseline=tokenizer.eos_token_id, measure="KL", target=target + ) + elif attr_func == "perturbation_REAGENT": + attr = llm_attributor.calculate_feature_ablation_sentences_mlm(example.prompt, target=target) + else: + raise ValueError(f"Unsupported perturbation attr_func {attr_func}") + elif "attention" in attr_func: + llm_attributor = llm_attr.LLMAttentionAttribution(model, tokenizer) + llm_attributor_ig = llm_attr.LLMGradientAttribtion(model, tokenizer) + attr = llm_attributor.calculate_attention_attribution(example.prompt, target=target) + attr_b = llm_attributor_ig.calculate_IG_per_generation( + example.prompt, 20, tokenizer.eos_token_id, batch_size=testing_dict["batch_size"], target=target + ) + attr.attribution_matrix = attr.attribution_matrix * attr_b.attribution_matrix + elif attr_func == "ifr_all_positions": + llm_attributor = llm_attr.LLMIFRAttribution( + model, + tokenizer, + chunk_tokens=testing_dict["chunk_tokens"], + sink_chunk_tokens=testing_dict["sink_chunk_tokens"], + ) + attr = llm_attributor.calculate_ifr_for_all_positions(example.prompt, target=target) + elif attr_func == "ifr_all_positions_output_only": + llm_attributor = llm_attr.LLMIFRAttribution( + model, + tokenizer, + chunk_tokens=testing_dict["chunk_tokens"], + sink_chunk_tokens=testing_dict["sink_chunk_tokens"], + ) + sink_span = tuple(example.sink_span) if example.sink_span else tuple(indices_to_explain) + attr = llm_attributor.calculate_ifr_for_all_positions_output_only( + example.prompt, + target=target, + sink_span=sink_span, + ) + elif attr_func == "ifr_multi_hop": + llm_attributor = llm_attr.LLMIFRAttribution( + model, + tokenizer, + chunk_tokens=testing_dict["chunk_tokens"], + sink_chunk_tokens=testing_dict["sink_chunk_tokens"], + ) + attr = llm_attributor.calculate_ifr_multi_hop( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict["n_hops"], + ) + elif attr_func == "ifr_in_all_gen": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionInAllGen( + model, + tokenizer, + chunk_tokens=testing_dict["chunk_tokens"], + sink_chunk_tokens=testing_dict["sink_chunk_tokens"], + ) + attr = llm_attributor.calculate_ifr_in_all_gen( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict["n_hops"], + ) + elif attr_func == "ifr_multi_hop_stop_words": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionImproved( + model, + tokenizer, + chunk_tokens=testing_dict["chunk_tokens"], + sink_chunk_tokens=testing_dict["sink_chunk_tokens"], + ) + attr = llm_attributor.calculate_ifr_multi_hop_stop_words( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict["n_hops"], + ) + elif attr_func == "ifr_multi_hop_both": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionBoth( + model, + tokenizer, + chunk_tokens=testing_dict["chunk_tokens"], + sink_chunk_tokens=testing_dict["sink_chunk_tokens"], + ) + attr = llm_attributor.calculate_ifr_multi_hop_both( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict["n_hops"], + ) + elif attr_func == "ifr_multi_hop_split_hop": + import ft_ifr_improve + + llm_attributor = ft_ifr_improve.LLMIFRAttributionSplitHop( + model, + tokenizer, + chunk_tokens=testing_dict["chunk_tokens"], + sink_chunk_tokens=testing_dict["sink_chunk_tokens"], + ) + attr = llm_attributor.calculate_ifr_multi_hop_split_hop( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict["n_hops"], + ) + elif attr_func == "attnlrp": + llm_attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + attr = llm_attributor.calculate_attnlrp_ft_hop0( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + neg_handling=str(testing_dict.get("attnlrp_neg_handling", "drop")), + norm_mode=str(testing_dict.get("attnlrp_norm_mode", "norm")), + ) + elif attr_func in ("ft_attnlrp", "attnlrp_aggregated_multi_hop"): + llm_attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + attr = llm_attributor.calculate_attnlrp_aggregated_multi_hop( + example.prompt, + target=target, + sink_span=tuple(example.sink_span) if example.sink_span else None, + thinking_span=tuple(example.thinking_span) if example.thinking_span else None, + n_hops=testing_dict["n_hops"], + neg_handling=str(testing_dict.get("attnlrp_neg_handling", "drop")), + norm_mode=str(testing_dict.get("attnlrp_norm_mode", "norm")), + ) + elif attr_func == "basic": + llm_attributor = llm_attr.LLMBasicAttribution(model, tokenizer) + attr = llm_attributor.calculate_basic_attribution(example.prompt, target=target) + else: + raise ValueError(f"Unsupported attr_func {attr_func}") + + seq_attr, row_attr, rec_attr = attr.get_all_token_attrs(indices_to_explain) + hop_payload = None + if bool(testing_dict.get("save_hop_traces", False)): + try: + hop_payload = _build_hop_trace_payload(attr_func, attr, indices_to_explain=indices_to_explain) + except Exception as exc: + print(f"[warn] hop trace extraction failed for {attr_func}: {exc}") + hop_payload = None + + user_prompt_indices = getattr(llm_attributor, "user_prompt_indices", None) + if isinstance(user_prompt_indices, list): + user_prompt_indices = [int(x) for x in user_prompt_indices] + else: + user_prompt_indices = None + + keep_prompt_token_indices = None + if attr_func in ("ifr_multi_hop_stop_words", "ifr_multi_hop_both"): + try: + import ft_ifr_improve + + keep_prompt_token_indices = ft_ifr_improve.keep_token_indices(list(attr.prompt_tokens)) + except Exception: + keep_prompt_token_indices = None + + return [seq_attr, row_attr, rec_attr], hop_payload, user_prompt_indices, keep_prompt_token_indices + + +def faithfulness_generation( + testing_dict, example: ds_utils.CachedExample, target: str, llm_evaluator +) -> Tuple[np.ndarray, Optional[Dict[str, np.ndarray]]]: + prompt = example.prompt + generation = target + + attr_func = str(testing_dict.get("attr_func") or "") + attr_list, hop_payload, user_prompt_indices, keep_prompt_token_indices = run_attribution( + testing_dict, example, target + ) + seq_attr = attr_list[0] + prompt_len = int(seq_attr.shape[1] - seq_attr.shape[0]) # cols=(P+G), rows=G + + results = [] + for attr in attr_list: + # Only use prompt-side attribution, matching evaluations/faithfulness.py + attr_prompt = attr[:, :prompt_len] + if attr_func in ("ifr_multi_hop_stop_words", "ifr_multi_hop_both") and keep_prompt_token_indices is not None: + import ft_ifr_improve + + scores = ft_ifr_improve.faithfulness_test_skip_tokens( + llm_evaluator, + attr_prompt, + prompt, + generation, + keep_prompt_token_indices=keep_prompt_token_indices, + user_prompt_indices=user_prompt_indices, + ) + elif user_prompt_indices is not None: + scores = _faithfulness_test_with_user_prompt_indices( + llm_evaluator, + attr_prompt, + prompt, + generation, + user_prompt_indices=user_prompt_indices, + ) + else: + scores = llm_evaluator.faithfulness_test(attr_prompt, prompt, generation) + results.append(scores) + + return np.array(results), hop_payload + + +def evaluate_dataset(args, dataset_name: str, examples: List[ds_utils.CachedExample], testing_dict): + out = evaluate_dataset_multi(args, dataset_name, examples, testing_dict, modes=["faithfulness_gen"]) + faith = out.get("faithfulness") + if not faith: + return None + return faith["mean"], faith["std"], faith["avg_time"] + + +def evaluate_dataset_recovery_ruler(args, dataset_name: str, examples: List[ds_utils.CachedExample], testing_dict): + out = evaluate_dataset_multi(args, dataset_name, examples, testing_dict, modes=["recovery_ruler"]) + rec = out.get("recovery") + if not rec: + return None + return rec["mean"], rec["std"], rec["avg_time"], rec["used"], rec["skipped"] + + +def main(): + parser = argparse.ArgumentParser("Experiment 2 runner (math skipped, AT2 skipped).") + parser.add_argument("--datasets", type=str, required=True, help="Comma-separated names or paths.") + parser.add_argument("--attr_funcs", type=str, required=True, help="Comma-separated attr funcs (no AT2).") + parser.add_argument("--model", type=str, default=None, help="HF repo id (required unless --model_path set).") + parser.add_argument("--model_path", type=str, default=None, help="Local path; overrides --model for loading.") + parser.add_argument("--cuda", type=str, default=None) + parser.add_argument("--cuda_num", type=int, default=0) + parser.add_argument("--num_examples", type=int, default=100) + parser.add_argument( + "--mode", + type=str, + nargs="+", + default=["faithfulness_gen"], + help=( + "One or more of: faithfulness_gen, recovery_ruler. " + "Accepts comma-separated values, e.g. '--mode faithfulness_gen,recovery_ruler' " + "or '--mode faithfulness_gen, recovery_ruler'." + ), + ) + parser.add_argument("--sample", type=int, default=None, help="Optional subsample before num_examples.") + parser.add_argument("--seed", type=int, default=42) + parser.add_argument("--chunk_tokens", type=int, default=128) + parser.add_argument("--sink_chunk_tokens", type=int, default=32) + parser.add_argument("--n_hops", type=int, default=3) + parser.add_argument( + "--attnlrp_neg_handling", + type=str, + choices=["drop", "abs"], + default="drop", + help="FT-AttnLRP: how to handle negative values after each hop (drop=clamp>=0, abs=absolute value).", + ) + parser.add_argument( + "--attnlrp_norm_mode", + type=str, + choices=["norm", "no_norm"], + default="norm", + help="FT-AttnLRP: norm enables per-hop global+thinking normalization + ratios; no_norm disables all three.", + ) + parser.add_argument("--data_root", type=str, default="exp/exp2/data", help="Filtered dataset cache directory.") + parser.add_argument("--output_root", type=str, default="exp/exp2/output", help="Directory to store evaluation outputs.") + parser.add_argument( + "--save_hop_traces", + action="store_true", + help=( + "Save per-sample trace artifacts (attribution vectors + per-sample metrics) under output_root/traces/. " + "For multi-hop methods, also saves per-hop token vectors (vh)." + ), + ) + args = parser.parse_args() + modes = _parse_modes(args.mode) + + if args.model_path: + model_name = args.model_path + elif args.model: + model_name = args.model + else: + raise SystemExit("Please set --model or --model_path.") + model_tag = args.model if args.model else Path(args.model_path).name + + datasets = [d.strip() for d in args.datasets.split(",") if d.strip()] + attr_funcs = [a.strip() for a in args.attr_funcs.split(",") if a.strip()] + + device = resolve_device(args) + model, tokenizer = load_model(model_name, device) + + max_input_len = { + "llama-1B": 5500, + "llama-3B": 4800, + "llama-8B": 3500, + "qwen-1.7B": 5500, + "qwen-4B": 3500, + "qwen-8B": 5000, + "qwen-32B": 1500, + "gemma-12B": 1500, + "gemma-27B": 2000, + }.get(args.model, 2000) + + for ds_name in datasets: + if "recovery_ruler" in modes and ds_name == "morehopqa": + raise SystemExit("recovery_ruler only supports RULER datasets (with needle_spans), not morehopqa.") + if "recovery_ruler" in modes and ds_name.startswith("math"): + raise SystemExit("recovery_ruler only supports RULER datasets (with needle_spans), not math.") + + # Resolve dataset (prefer prepared cache under data_root) + cached_path = Path(args.data_root) / f"{ds_name}.jsonl" + if cached_path.exists(): + examples = ds_utils.load_cached(cached_path, sample=args.sample, seed=args.seed) + else: + # allow direct cached path or raw loader + p = Path(ds_name) + if p.exists(): + examples = ds_utils.load_cached(p, sample=args.sample, seed=args.seed) + else: + hint = "please run exp/exp2/sample_and_filter.py first (or pass an explicit cached JSONL path)." + if ds_name.startswith("math"): + hint = "please run exp/exp2/map_math_mine_to_exp2_cache.py first (or pass an explicit cached JSONL path)." + raise SystemExit(f"Missing exp2 cache for '{ds_name}'. Expected {cached_path}; {hint}") + + for attr_func in attr_funcs: + if attr_func.lower() == "at2": + print("Skipping AT2 as requested.") + continue + + testing_dict: Dict[str, any] = { + "model": model, + "model_tag": model_tag, + "tokenizer": tokenizer, + "attr_func": attr_func, + "max_input_len": max_input_len, + "chunk_tokens": args.chunk_tokens, + "sink_chunk_tokens": args.sink_chunk_tokens, + "n_hops": args.n_hops, + "attnlrp_neg_handling": args.attnlrp_neg_handling, + "attnlrp_norm_mode": args.attnlrp_norm_mode, + "device": device, + "batch_size": 1, + "save_hop_traces": bool(args.save_hop_traces), + } + result = evaluate_dataset_multi(args, ds_name, examples, testing_dict, modes=modes) + + if "faithfulness_gen" in modes: + faith = result.get("faithfulness") + if not faith: + print(f"No faithfulness results for {ds_name} with {attr_func}.") + else: + mean = faith["mean"] + std = faith["std"] + avg_time = float(faith["avg_time"]) + + out_dir = Path(args.output_root) / "faithfulness" / ds_name / model_tag + out_dir.mkdir(parents=True, exist_ok=True) + filename = f"{attr_func}_{args.num_examples}_examples.csv" + with open(out_dir / filename, "w") as f: + f.write("Method,RISE,MAS,RISE+AP\n") + f.write(",".join(["Seq Attr Scores Mean"] + [str(x) for x in mean[0].tolist()]) + "\n") + f.write(",".join(["Row Attr Scores Mean"] + [str(x) for x in mean[1].tolist()]) + "\n") + f.write(",".join(["Recursive Attr Scores Mean"] + [str(x) for x in mean[2].tolist()]) + "\n") + f.write(",".join(["Seq Attr Scores Var"] + [str(x) for x in std[0].tolist()]) + "\n") + f.write(",".join(["Row Attr Scores Var"] + [str(x) for x in std[1].tolist()]) + "\n") + f.write(",".join(["Recursive Attr Scores Var"] + [str(x) for x in std[2].tolist()]) + "\n") + f.write(f"Avg Sample Time (s),{avg_time}\n") + print(f"[{ds_name}] {attr_func} -> {out_dir/filename} (avg sample time: {avg_time:.2f}s)") + + if "recovery_ruler" in modes: + rec = result.get("recovery") + if not rec: + print(f"No recovery results for {ds_name} with {attr_func}.") + else: + mean = rec["mean"] + std = rec["std"] + avg_time = float(rec["avg_time"]) + used = int(rec["used"]) + skipped = int(rec["skipped"]) + + out_dir = Path(args.output_root) / "recovery" / ds_name / model_tag + out_dir.mkdir(parents=True, exist_ok=True) + filename = f"{attr_func}_{args.num_examples}_examples.csv" + with open(out_dir / filename, "w") as f: + f.write("Method,Recovery@10%\n") + f.write(f"Seq Attr Recovery Mean,{mean[0]}\n") + f.write(f"Row Attr Recovery Mean,{mean[1]}\n") + f.write(f"Recursive Attr Recovery Mean,{mean[2]}\n") + f.write(f"Seq Attr Recovery Std,{std[0]}\n") + f.write(f"Row Attr Recovery Std,{std[1]}\n") + f.write(f"Recursive Attr Recovery Std,{std[2]}\n") + f.write(f"Examples Used,{used}\n") + f.write(f"Examples Skipped,{skipped}\n") + f.write(f"Avg Sample Time (s),{avg_time}\n") + print( + f"[{ds_name}] {attr_func} -> {out_dir/filename} " + f"(used={used} skipped={skipped} avg sample time: {avg_time:.2f}s)" + ) + + +if __name__ == "__main__": + main() diff --git a/exp/exp2/sample_and_filter.py b/exp/exp2/sample_and_filter.py new file mode 100644 index 0000000000000000000000000000000000000000..b03cadba062916618deb70a8d918037cfd5b961a --- /dev/null +++ b/exp/exp2/sample_and_filter.py @@ -0,0 +1,363 @@ +#!/usr/bin/env python3 +""" +Dataset sampler for Experiment 2. + +Steps: +- Load a dataset item (MoreHopQA / HotpotQA / RULER niah / RULER vt). +- Call the generation model (qwen3-235b-a22b-2507) with a system prompt that + asks for brief reasoning and a final answer wrapped in \\box{}. +- Enforce the output format: keep only generations that look like + " + final \\box{} answer" with nothing after the box. +- Call the judge model (deepseek-v3-1-terminus) to check whether the boxed + answer matches the dataset reference answer; keep only judged True samples. +- Rebuild `target` as "\\n" and store filtered + samples to exp/exp2/data/.jsonl (or a custom path) with inferred spans. +""" + +from __future__ import annotations + +import argparse +import json +import os +import sys +import time +import urllib.error +import urllib.request +from pathlib import Path +from typing import Any, Dict, Iterable, List, Optional + +from transformers import AutoTokenizer +from tqdm import tqdm + +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + +from exp.exp2.dataset_utils import ( + CachedExample, + DatasetLoader, + attach_spans_from_answer, + split_boxed_generation, +) + + +class RateLimitError(RuntimeError): + """Raised when API returns 429; carries a suggested wait time.""" + + def __init__(self, wait_seconds: float, detail: str) -> None: + super().__init__(detail) + self.wait_seconds = wait_seconds + +# GEN_SYSTEM_PROMPT = ( +# "You are a careful reasoning assistant. " +# "Before answering, engage in an extremely detailed and exhaustive chain of thought. **No fewer than 2k tokens.** " +# "Do not skip any logical steps, even if they seem obvious. " +# "Process this freely and naturally without using specific headers or strict formatting. " +# "When you reach the conclusion, wrap the entire final sentence containing the answer inside \\box{}. " +# "Ensure the box wraps the **sentence** that naturally delivers the answer. DO NOT rewrite the answer word for the box separately." +# ) + +GEN_SYSTEM_PROMPT = ( + "You are a reasoning assistant. " + "Before answering, engage in an chain of thought. " + "Process this freely and naturally without using specific headers or strict formatting. " + "When you reach the conclusion, wrap the entire final sentence containing the answer inside \\box{}. " + "Ensure the box wraps the **sentence** that naturally delivers the answer. DO NOT rewrite the answer word for the box separately." +) + +JUDGE_SYSTEM_PROMPT = ( + "You verify whether the model's boxed answer matches the reference answer. " + "Reply strictly with True or False and nothing else." +) + + +def call_chat_api( + api_base: str, + api_key: str, + model: str, + messages: List[Dict[str, str]], + *, + timeout: int, + max_tokens: int, + temperature: float, + cache_ttl: int, + cache_namespace: Optional[str], + rate_limit_delay: Optional[float] = None, +) -> str: + url = api_base.rstrip("/") + "/chat/completions" + payload: Dict[str, Any] = { + "model": model, + "messages": messages, + "max_tokens": max_tokens, + "temperature": temperature, + } + if cache_ttl > 0: + cache_obj: Dict[str, Any] = {"ttl": cache_ttl} + if cache_namespace: + cache_obj["namespace"] = cache_namespace + payload["cache"] = cache_obj + + data = json.dumps(payload).encode("utf-8") + headers = {"Content-Type": "application/json"} + if api_key: + headers["Authorization"] = f"Bearer {api_key}" + + req = urllib.request.Request(url, data=data, headers=headers, method="POST") + opener = urllib.request.build_opener(urllib.request.ProxyHandler({})) + try: + with opener.open(req, timeout=timeout) as resp: + resp_bytes = resp.read() + except urllib.error.HTTPError as e: + detail = e.read().decode("utf-8", errors="ignore") if hasattr(e, "read") else "" + if e.code == 429: + retry_after = None + if hasattr(e, "headers") and e.headers: + retry_after_header = e.headers.get("Retry-After") + if retry_after_header: + try: + retry_after = float(retry_after_header) + except ValueError: + retry_after = None + wait = retry_after or rate_limit_delay or 5.0 + raise RateLimitError(wait, f"API HTTP 429: {detail}") from e + raise RuntimeError(f"API HTTP error {e.code}: {detail}") from e + except urllib.error.URLError as e: + raise RuntimeError(f"API request failed: {e}") from e + + try: + response = json.loads(resp_bytes.decode("utf-8")) + except json.JSONDecodeError as e: + raise RuntimeError(f"Failed to decode API response: {resp_bytes!r}") from e + + choices = response.get("choices", []) + if not choices: + raise RuntimeError(f"Empty choices from API: {response}") + content = choices[0].get("message", {}).get("content", "") + if not content: + raise RuntimeError(f"Empty content from API: {response}") + return content.strip() + + +def build_gen_messages(prompt: str) -> List[Dict[str, str]]: + return [ + {"role": "system", "content": GEN_SYSTEM_PROMPT}, + {"role": "user", "content": prompt}, + ] + + +def build_judge_messages(reference_answer: str, candidate_answer: str) -> List[Dict[str, str]]: + user = ( + "Decide if the model's boxed answer matches the reference answer.\n" + f"Reference answer: {reference_answer}\n" + f"Model boxed answer (only the content inside \\box{{}}): {candidate_answer}\n" + "Output only True if they are semantically consistent; otherwise output False." + ) + return [ + {"role": "system", "content": JUDGE_SYSTEM_PROMPT}, + {"role": "user", "content": user}, + ] + + +def parse_bool(text: str) -> bool: + first = text.strip().splitlines()[0].strip().lower() + if first in {"true", "yes"}: + return True + if first in {"false", "no"}: + return False + # fallback: check substring + if "true" in first and "false" not in first: + return True + if "false" in first: + return False + raise ValueError(f"Cannot parse boolean from: {text!r}") + + +def write_cache(out_path: Path, examples: Iterable[CachedExample]) -> int: + out_path.parent.mkdir(parents=True, exist_ok=True) + count = 0 + with out_path.open("w", encoding="utf-8") as f: + for ex in examples: + obj: Dict[str, Any] = { + "prompt": ex.prompt, + "target": ex.target, + "indices_to_explain": ex.indices_to_explain, + "attr_mask_indices": ex.attr_mask_indices, + "sink_span": ex.sink_span, + "thinking_span": ex.thinking_span, + "metadata": ex.metadata, + } + f.write(json.dumps(obj, ensure_ascii=False) + "\n") + count += 1 + return count + + +def main(): + parser = argparse.ArgumentParser("Sample and filter dataset examples for exp2.") + parser.add_argument( + "--dataset", + type=str, + required=True, + help="morehopqa | hotpotqa_long | niah_* | vt_* | | ", + ) + parser.add_argument("--max_examples", type=int, default=100, help="Number of raw examples to sample before filtering.") + parser.add_argument("--seed", type=int, default=42) + parser.add_argument("--api_base", type=str, default="http://localhost:4000/v1", help="Chat API base URL.") + parser.add_argument("--api_key", type=str, default=None, help="API key; defaults to FLASHTRACE_API_KEY/OPENAI_API_KEY.") + parser.add_argument("--generator_model", type=str, default="qwen3-235b-a22b-2507") + parser.add_argument("--judge_model", type=str, default="deepseek-v3-1-terminus") + parser.add_argument("--api_timeout", type=int, default=300) + parser.add_argument("--api_max_tokens", type=int, default=8192) + parser.add_argument("--api_temperature", type=float, default=0.0) + parser.add_argument("--api_cache_ttl", type=int, default=600) + parser.add_argument("--api_cache_namespace", type=str, default="flashtrace-exp2") + parser.add_argument("--retry_delay", type=float, default=2.0) + parser.add_argument("--retries", type=int, default=2, help="Additional retries on API failure.") + parser.add_argument("--request_interval", type=float, default=1.0, help="Sleep seconds between generation calls.") + parser.add_argument("--judge_interval", type=float, default=1.0, help="Sleep seconds between judge calls.") + parser.add_argument("--tokenizer_model", type=str, default=None, help="Tokenizer path for span extraction (default: generator model).") + parser.add_argument("--data_root", type=str, default="exp/exp2/data", help="Output directory for filtered caches.") + parser.add_argument("--out", type=str, default=None, help="Optional explicit output path (JSONL).") + parser.add_argument("--rate_limit_delay", type=float, default=5.0, help="Seconds to wait on HTTP 429 before retrying.") + args = parser.parse_args() + + api_key = args.api_key or os.environ.get("FLASHTRACE_API_KEY") or os.environ.get("OPENAI_API_KEY") + if not api_key: + raise SystemExit("Set --api_key or FLASHTRACE_API_KEY/OPENAI_API_KEY for API access.") + + loader = DatasetLoader(seed=args.seed, data_root=args.data_root) + # Load full dataset; we will stop early once enough kept examples are collected. + raw_examples = loader.load_raw(args.dataset, sample=None) + if not raw_examples: + raise SystemExit("No examples loaded.") + + tok_name = args.tokenizer_model or args.generator_model + tok_path = Path(tok_name) + if tok_path.exists(): + tokenizer = AutoTokenizer.from_pretrained(tok_path.as_posix(), local_files_only=True) + else: + tokenizer = AutoTokenizer.from_pretrained(tok_name) + tokenizer.pad_token = tokenizer.eos_token + + kept: List[CachedExample] = [] + total = len(raw_examples) + kept_bar = tqdm(total=args.max_examples, desc="Kept (judge=True)", position=1, leave=False) + attempted = 0 + + for idx, ex in enumerate(tqdm(raw_examples, total=total, desc="Sampling"), 1): + if len(kept) >= args.max_examples: + break + reference_answer = ex.metadata.get("reference_answer") or ex.target or "" + gen_messages = build_gen_messages(ex.prompt) + attempted = idx + + # Step 1: generation + for attempt in range(args.retries + 1): + try: + generation = call_chat_api( + args.api_base, + api_key, + args.generator_model, + gen_messages, + timeout=args.api_timeout, + max_tokens=args.api_max_tokens, + temperature=args.api_temperature, + cache_ttl=args.api_cache_ttl, + cache_namespace=args.api_cache_namespace, + rate_limit_delay=args.rate_limit_delay, + ) + break + except RateLimitError as e: + if attempt >= args.retries: + raise + time.sleep(e.wait_seconds) + except Exception: # noqa: BLE001 + if attempt >= args.retries: + raise + time.sleep(args.retry_delay) + if args.request_interval > 0: + time.sleep(args.request_interval) + + parsed = split_boxed_generation(generation) + if not parsed: + print(f"[{idx}/{total}] skipped=format") + continue + + thinking_text, boxed_segment, boxed_answer = parsed + target_text = f"{thinking_text}\n{boxed_answer}" if thinking_text else boxed_answer + judge_messages = build_judge_messages(reference_answer, boxed_answer) + + ok = False + judge_resp = "" + for attempt in range(args.retries + 1): + try: + judge_resp = call_chat_api( + args.api_base, + api_key, + args.judge_model, + judge_messages, + timeout=args.api_timeout, + max_tokens=64, + temperature=0.0, + cache_ttl=args.api_cache_ttl, + cache_namespace=args.api_cache_namespace, + rate_limit_delay=args.rate_limit_delay, + ) + ok = parse_bool(judge_resp) + break + except RateLimitError as e: + if attempt >= args.retries: + raise + time.sleep(e.wait_seconds) + except Exception: # noqa: BLE001 + if attempt >= args.retries: + raise + time.sleep(args.retry_delay) + if args.judge_interval > 0: + time.sleep(args.judge_interval) + + status = "kept" if ok else "filtered" + print(f"[{idx}/{total}] judge={status}") + if not ok: + continue + + new_meta = dict(ex.metadata) + new_meta["reference_answer"] = reference_answer + new_meta["judge_response"] = judge_resp + + new_ex = CachedExample( + prompt=ex.prompt, + target=target_text, + indices_to_explain=None, + attr_mask_indices=ex.attr_mask_indices, + sink_span=None, + thinking_span=None, + metadata=new_meta, + ) + new_ex = attach_spans_from_answer(new_ex, tokenizer, boxed_answer) + if not (isinstance(new_ex.sink_span, list) and len(new_ex.sink_span) == 2): + print(f"[{idx}/{total}] skipped=span") + continue + + # Token-level indices_to_explain: boxed-inner answer token span in target (closed interval). + new_ex = CachedExample( + prompt=new_ex.prompt, + target=new_ex.target, + indices_to_explain=new_ex.sink_span, + attr_mask_indices=new_ex.attr_mask_indices, + sink_span=new_ex.sink_span, + thinking_span=new_ex.thinking_span, + metadata=new_ex.metadata, + ) + kept.append(new_ex) + kept_bar.update(1) + + kept_bar.close() + + out_path = Path(args.out) if args.out else Path(args.data_root) / f"{args.dataset}.jsonl" + written = write_cache(out_path, kept) + attempted_total = attempted or 0 + print(f"Kept {written} / target {args.max_examples} (attempted {attempted_total} / {total}) -> {out_path}") + + +if __name__ == "__main__": + main() diff --git a/exp/exp3/README.md b/exp/exp3/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d17cce6bceaf6886a28c209b14ec3921ea009229 --- /dev/null +++ b/exp/exp3/README.md @@ -0,0 +1,50 @@ +# FlashTrace ๅฎž้ชŒ 3๏ผš้•ฟ/็Ÿญ CoT ๅฏนๆฏ”๏ผˆcase study๏ผ‰ + +ๆœฌ็›ฎๅฝ•ๆไพ›ไธ€ไธชใ€Œ้•ฟ/็Ÿญ CoTใ€็š„ๆœ€ๅฐๅฏๅค็Žฐๅฎž้ชŒ๏ผš +- ไปŽ RULER `niah_mq_q2 (1024)` ไธญๅˆ†ๅˆซ็ญ›ๅ‡บ๏ผš + - short-CoT๏ผš็ŸญๆŽจ็† + `\box{}` ๆœ€็ปˆ็ญ”ๆกˆ + - long-CoT๏ผš้•ฟๆŽจ็† + `\box{}` ๆœ€็ปˆ็ญ”ๆกˆ +- ๅช่ท‘ `attnlrp`๏ผˆhop0๏ผ‰ๅนถๅช่ฎก็ฎ— token-level `recovery@10%`๏ผˆgold ๆฅ่‡ช `needle_spans`๏ผ‰ใ€‚ +- ่ฝ็›˜ trace๏ผˆnpz + manifest๏ผ‰ๅˆฐ `exp/exp3/output/`๏ผŒๆ ผๅผๅฏน้ฝ `exp/exp2/run_exp.py` ็š„ trace ไน ๆƒฏใ€‚ + +## 1) ้‡‡ๆ ทไธŽ่ฟ‡ๆปค๏ผˆ็”Ÿๆˆ + judge๏ผ‰ + +้ป˜่ฎค่ฏปๅ–๏ผš +`data/ruler_multihop/1024/niah_mq_q2/validation.jsonl` + +้œ€่ฆไธ€ไธช OpenAI-compatible ็š„ chat API๏ผˆ้ป˜่ฎค `http://localhost:4000/v1`๏ผ‰ไปฅๅŠ API keyใ€‚ + +```bash +export FLASHTRACE_API_KEY=... # ๆˆ– OPENAI_API_KEY + +python exp/exp3/sample_and_filter.py \ + --tokenizer_model /opt/share/models/Qwen/Qwen3-8B/ \ + --min_long_thinking_tokens 512 \ + --max_short_thinking_tokens 256 +``` + +่พ“ๅ‡บ๏ผˆ้ป˜่ฎค๏ผ‰๏ผš +- `exp/exp3/data/niah_mq_q2_short_cot.jsonl` +- `exp/exp3/data/niah_mq_q2_long_cot.jsonl` + +่ฏดๆ˜Ž๏ผš +- ้ป˜่ฎคๅ„้‡‡ 1 ๆก๏ผ›ๅฏ็”จ `--max_short` / `--max_long` ๅˆ†ๅˆซๆŒ‡ๅฎšๆ•ฐ้‡๏ผˆ`--max_pairs` ๆ˜ฏไธค่€…็š„ๅ…ผๅฎนๅˆซๅ๏ผ‰ใ€‚ + +## 2) ๅฝ’ๅ› ไธŽ recovery๏ผˆAttnLRP hop0๏ผ‰ + +```bash +python exp/exp3/run_exp.py \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 3,4,5,7 +``` + +่พ“ๅ‡บ๏ผš +- recovery CSV๏ผš`exp/exp3/output/recovery///attnlrp_1_examples.csv` +- trace๏ผš`exp/exp3/output/traces////ex_*.npz` + `manifest.jsonl` +- ๆฑ‡ๆ€ป JSON๏ผš`exp/exp3/output/recovery/summary_.json` + +ๅธธ็”จๅ‚ๆ•ฐ๏ผš +- `--top_fraction`๏ผšrecovery ็š„ top fraction๏ผˆ้ป˜่ฎค 0.1๏ผ‰ +- `--attnlrp_neg_handling drop|abs` +- `--attnlrp_norm_mode norm|no_norm` diff --git a/exp/exp3/extract_segment_weights.py b/exp/exp3/extract_segment_weights.py new file mode 100644 index 0000000000000000000000000000000000000000..695af1588e102927635a01a2553ca381ec035f46 --- /dev/null +++ b/exp/exp3/extract_segment_weights.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python3 +""" +Extract CoT/output segment attribution weights from exp3 trace artifacts. + +Background +---------- +exp/exp3/run_exp.py saves per-sample trace npz files that contain token-level +importance vectors over the FULL (prompt + generation) token sequence: + - v_seq_all: sum over rows of seq attribution matrix (shape [P+G]) + - v_row_all: row attribution vector for indices_to_explain (shape [P+G]) + - v_rec_all: recursive attribution vector for indices_to_explain (shape [P+G]) + +For exp3 cached samples, we also have generation-token spans: + - thinking_span_gen: CoT span [start,end] in generation-token coordinates + - sink_span_gen: output span [start,end] in generation-token coordinates + +This script slices v_*_all into: + - cot: tokens in thinking_span_gen (offset by prompt_len) + - output: tokens in sink_span_gen (offset by prompt_len) + +and reports segment sums/fractions (and optionally writes a JSON summary). +""" + +from __future__ import annotations + +import argparse +import json +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Dict, List, Optional, Tuple + +import numpy as np + + +@dataclass(frozen=True) +class TracePaths: + dataset: str + model_tag: str + run_tag: str + npz_path: Path + + +def _pick_latest_subdir(path: Path) -> Optional[Path]: + if not path.exists(): + return None + subs = [p for p in path.iterdir() if p.is_dir()] + if not subs: + return None + subs.sort(key=lambda p: p.stat().st_mtime, reverse=True) + return subs[0] + + +def _resolve_trace_paths( + *, + output_root: Path, + dataset: str, + model_tag: Optional[str], + run_tag: Optional[str], + example_idx: int, +) -> TracePaths: + base = output_root / "traces" / dataset + if not base.exists(): + raise FileNotFoundError(f"Trace dataset dir not found: {base}") + + if model_tag is None: + model_dirs = [p for p in base.iterdir() if p.is_dir()] + if not model_dirs: + raise FileNotFoundError(f"No model subdir under: {base}") + if len(model_dirs) != 1: + raise SystemExit(f"Multiple model dirs under {base}; pass --model_tag. Found: {[p.name for p in model_dirs]}") + model_dir = model_dirs[0] + model_tag = model_dir.name + else: + model_dir = base / model_tag + if not model_dir.exists(): + raise FileNotFoundError(f"Trace model dir not found: {model_dir}") + + if run_tag is None: + run_dir = _pick_latest_subdir(model_dir) + if run_dir is None: + raise FileNotFoundError(f"No run subdir under: {model_dir}") + run_tag = run_dir.name + else: + run_dir = model_dir / run_tag + if not run_dir.exists(): + raise FileNotFoundError(f"Trace run dir not found: {run_dir}") + + npz_name = f"ex_{int(example_idx):06d}.npz" + npz_path = run_dir / npz_name + if not npz_path.exists(): + raise FileNotFoundError(f"Trace npz not found: {npz_path}") + + return TracePaths(dataset=dataset, model_tag=model_tag, run_tag=run_tag, npz_path=npz_path) + + +def _as_span(arr: Any) -> Optional[Tuple[int, int]]: + if arr is None: + return None + try: + a = np.asarray(arr).reshape(-1).tolist() + except Exception: + return None + if len(a) != 2: + return None + try: + start = int(a[0]) + end = int(a[1]) + except Exception: + return None + if start < 0 or end < start: + return None + return start, end + + +def _segment_stats(v: np.ndarray, start: int, end: int) -> Dict[str, float]: + if end < start: + return {"sum": 0.0, "mean": 0.0, "max": 0.0} + seg = v[start : end + 1] + if seg.size == 0: + return {"sum": 0.0, "mean": 0.0, "max": 0.0} + return { + "sum": float(seg.sum()), + "mean": float(seg.mean()), + "max": float(seg.max()), + } + + +def _slice_segment(v: np.ndarray, start: int, end: int) -> List[float]: + if end < start: + return [] + seg = v[start : end + 1] + return [float(x) for x in seg.tolist()] + + +def extract_one(npz_path: Path) -> Dict[str, Any]: + d = np.load(npz_path) + required = ["prompt_len", "gen_len", "v_seq_all", "v_row_all", "v_rec_all"] + for k in required: + if k not in d: + raise KeyError(f"Missing key in trace npz {npz_path}: {k}") + + prompt_len = int(np.asarray(d["prompt_len"]).item()) + gen_len = int(np.asarray(d["gen_len"]).item()) + total_len = prompt_len + gen_len + + v_seq_all = np.asarray(d["v_seq_all"], dtype=np.float64).reshape(-1) + v_row_all = np.asarray(d["v_row_all"], dtype=np.float64).reshape(-1) + v_rec_all = np.asarray(d["v_rec_all"], dtype=np.float64).reshape(-1) + for name, v in [("v_seq_all", v_seq_all), ("v_row_all", v_row_all), ("v_rec_all", v_rec_all)]: + if int(v.size) != int(total_len): + raise ValueError(f"{name} length mismatch: expected {total_len}, got {int(v.size)}") + + sink_span_gen = _as_span(d.get("sink_span_gen")) + thinking_span_gen = _as_span(d.get("thinking_span_gen")) + if sink_span_gen is None: + raise KeyError("Trace missing sink_span_gen; cannot define output span.") + if thinking_span_gen is None: + # Best-effort: infer thinking span as [0, sink_start-1]. + sink_start, _ = sink_span_gen + thinking_span_gen = (0, max(0, sink_start - 1)) + + think_start_g, think_end_g = thinking_span_gen + sink_start_g, sink_end_g = sink_span_gen + + cot_start = prompt_len + think_start_g + cot_end = min(prompt_len + think_end_g, total_len - 1) + out_start = prompt_len + sink_start_g + out_end = min(prompt_len + sink_end_g, total_len - 1) + + def pack(v: np.ndarray) -> Dict[str, Any]: + total = float(v.sum()) + cot = _segment_stats(v, cot_start, cot_end) + out = _segment_stats(v, out_start, out_end) + denom = cot["sum"] + out["sum"] + return { + "total_sum": total, + "cot": { + "start_abs": int(cot_start), + "end_abs": int(cot_end), + "len": int(max(0, cot_end - cot_start + 1)), + **cot, + "fraction_of_total": float(cot["sum"] / total) if total > 0 else float("nan"), + "fraction_of_cot_plus_output": float(cot["sum"] / denom) if denom > 0 else float("nan"), + }, + "output": { + "start_abs": int(out_start), + "end_abs": int(out_end), + "len": int(max(0, out_end - out_start + 1)), + **out, + "fraction_of_total": float(out["sum"] / total) if total > 0 else float("nan"), + "fraction_of_cot_plus_output": float(out["sum"] / denom) if denom > 0 else float("nan"), + }, + "cot_weights": _slice_segment(v, cot_start, cot_end), + "output_weights": _slice_segment(v, out_start, out_end), + } + + return { + "prompt_len": int(prompt_len), + "gen_len": int(gen_len), + "total_len": int(total_len), + "thinking_span_gen": [int(think_start_g), int(think_end_g)], + "sink_span_gen": [int(sink_start_g), int(sink_end_g)], + "seq": pack(v_seq_all), + "row": pack(v_row_all), + "rec": pack(v_rec_all), + } + + +def main() -> None: + parser = argparse.ArgumentParser("Extract CoT/output weights from exp3 traces.") + parser.add_argument("--output_root", type=str, default="exp/exp3/output") + parser.add_argument("--dataset_tag", type=str, default="niah_mq_q2") + parser.add_argument("--model_tag", type=str, default=None, help="If omitted, auto-detect when unique.") + parser.add_argument("--run_tag", type=str, default=None, help="If omitted, picks the latest run subdir.") + parser.add_argument("--example_idx", type=int, default=0) + parser.add_argument("--out", type=str, default=None, help="Optional JSON output path.") + args = parser.parse_args() + + output_root = Path(args.output_root) + datasets = [f"{args.dataset_tag}_short_cot", f"{args.dataset_tag}_long_cot"] + + results: List[Dict[str, Any]] = [] + for ds_name in datasets: + paths = _resolve_trace_paths( + output_root=output_root, + dataset=ds_name, + model_tag=args.model_tag, + run_tag=args.run_tag, + example_idx=args.example_idx, + ) + out = extract_one(paths.npz_path) + out["dataset"] = paths.dataset + out["model_tag"] = paths.model_tag + out["run_tag"] = paths.run_tag + out["npz_path"] = str(paths.npz_path) + results.append(out) + + text = json.dumps(results, ensure_ascii=False, indent=2) + if args.out: + out_path = Path(args.out) + out_path.parent.mkdir(parents=True, exist_ok=True) + out_path.write_text(text + "\n", encoding="utf-8") + print(f"Wrote -> {out_path}") + else: + print(text) + + +if __name__ == "__main__": + main() + diff --git a/exp/exp3/part_weights.py b/exp/exp3/part_weights.py new file mode 100644 index 0000000000000000000000000000000000000000..331190ae903dbad6758cd8d1959fa0626a36116e --- /dev/null +++ b/exp/exp3/part_weights.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python3 +""" +Compute attribution mass on (input, cot, output) segments from exp3 trace npz files. + +Definitions (token-level, aligned with exp2/exp3 runners): +- input : prompt-side tokens (user prompt), indices [0, prompt_len) +- cot : generation tokens in thinking span, indices [prompt_len + t0, prompt_len + t1] +- output : generation tokens in sink span (answer), indices [prompt_len + s0, prompt_len + s1] + +The trace stores token-importance vectors: + - v_seq_all, v_row_all, v_rec_all (length = prompt_len + gen_len) + +This script sums those vectors over each segment and reports both absolute sums +and fractions of the total sum. +""" + +from __future__ import annotations + +import argparse +import json +from dataclasses import dataclass +from pathlib import Path +from typing import Dict, Iterable, List, Optional, Tuple + +import numpy as np + + +@dataclass(frozen=True) +class TraceRun: + dataset: str + model: str + run_dir: Path + + +def _pick_single_subdir(parent: Path) -> Path: + subdirs = [p for p in parent.iterdir() if p.is_dir()] + if not subdirs: + raise FileNotFoundError(f"No subdirectories found under {parent}") + if len(subdirs) == 1: + return subdirs[0] + subdirs.sort(key=lambda p: p.stat().st_mtime, reverse=True) + return subdirs[0] + + +def _resolve_run( + trace_root: Path, + *, + dataset: str, + model: Optional[str], + run_tag: Optional[str], +) -> TraceRun: + ds_dir = trace_root / dataset + if not ds_dir.exists(): + raise FileNotFoundError(f"Dataset trace directory not found: {ds_dir}") + + if model is None: + model_dir = _pick_single_subdir(ds_dir) + else: + model_dir = ds_dir / model + if not model_dir.exists(): + raise FileNotFoundError(f"Model trace directory not found: {model_dir}") + + if run_tag is None: + run_dir = _pick_single_subdir(model_dir) + else: + run_dir = model_dir / run_tag + if not run_dir.exists(): + raise FileNotFoundError(f"Run directory not found: {run_dir}") + + return TraceRun(dataset=dataset, model=model_dir.name, run_dir=run_dir) + + +def _iter_manifest(run_dir: Path) -> Iterable[dict]: + manifest = run_dir / "manifest.jsonl" + if not manifest.exists(): + raise FileNotFoundError(f"Missing manifest: {manifest}") + with manifest.open("r", encoding="utf-8") as f: + for line in f: + line = line.strip() + if line: + yield json.loads(line) + + +def _as_span(arr: np.ndarray, *, name: str) -> Tuple[int, int]: + if arr is None: + raise ValueError(f"Missing {name} in trace npz.") + a = np.asarray(arr).reshape(-1) + if a.size != 2: + raise ValueError(f"Expected {name} to have 2 ints, got shape {a.shape}.") + return int(a[0]), int(a[1]) + + +def _segment_sums( + v: np.ndarray, + *, + prompt_len: int, + gen_len: int, + thinking_span_gen: Optional[Tuple[int, int]], + sink_span_gen: Optional[Tuple[int, int]], +) -> Dict[str, float]: + total_len = int(prompt_len) + int(gen_len) + if int(v.shape[0]) != total_len: + raise ValueError(f"Vector length mismatch: len(v)={int(v.shape[0])} vs prompt_len+gen_len={total_len}.") + + v = np.asarray(v, dtype=np.float64).reshape(-1) + prompt_len = int(prompt_len) + gen_len = int(gen_len) + + # Default: no cot/output when spans missing (should not happen in exp3). + think_start, think_end = (0, -1) if thinking_span_gen is None else thinking_span_gen + sink_start, sink_end = (0, -1) if sink_span_gen is None else sink_span_gen + + # Clamp spans into [0, gen_len-1]. + def _clamp_span(a: int, b: int) -> Tuple[int, int]: + a = max(0, min(int(a), gen_len - 1)) + b = max(0, min(int(b), gen_len - 1)) + if b < a: + return 0, -1 + return a, b + + think_start, think_end = _clamp_span(think_start, think_end) + sink_start, sink_end = _clamp_span(sink_start, sink_end) + + mask = np.zeros((total_len,), dtype=bool) + # input = all prompt tokens + input_slice = slice(0, prompt_len) + mask[input_slice] = True + + cot_slice = slice(prompt_len + think_start, prompt_len + think_end + 1) if think_end >= think_start else slice(0, 0) + output_slice = slice(prompt_len + sink_start, prompt_len + sink_end + 1) if sink_end >= sink_start else slice(0, 0) + mask[cot_slice] = True + mask[output_slice] = True + + input_sum = float(v[input_slice].sum()) + cot_sum = float(v[cot_slice].sum()) if think_end >= think_start else 0.0 + output_sum = float(v[output_slice].sum()) if sink_end >= sink_start else 0.0 + other_sum = float(v[~mask].sum()) + total_sum = float(v.sum()) + + return { + "total": total_sum, + "input": input_sum, + "cot": cot_sum, + "output": output_sum, + "other": other_sum, + } + + +def _with_fracs(sums: Dict[str, float]) -> Dict[str, float]: + total = float(sums.get("total") or 0.0) + if total <= 0.0: + return {**sums, "input_frac": float("nan"), "cot_frac": float("nan"), "output_frac": float("nan"), "other_frac": float("nan")} + return { + **sums, + "input_frac": float(sums["input"]) / total, + "cot_frac": float(sums["cot"]) / total, + "output_frac": float(sums["output"]) / total, + "other_frac": float(sums["other"]) / total, + } + + +def _analyze_npz(npz_path: Path) -> Dict[str, dict]: + d = np.load(npz_path) + prompt_len = int(np.asarray(d["prompt_len"]).item()) + gen_len = int(np.asarray(d["gen_len"]).item()) + thinking_span_gen = _as_span(d["thinking_span_gen"], name="thinking_span_gen") if "thinking_span_gen" in d.files else None + sink_span_gen = _as_span(d["sink_span_gen"], name="sink_span_gen") if "sink_span_gen" in d.files else None + + out: Dict[str, dict] = {"prompt_len": prompt_len, "gen_len": gen_len} + for key in ("v_seq_all", "v_row_all", "v_rec_all"): + if key not in d.files: + raise ValueError(f"Missing {key} in trace npz: {npz_path}") + sums = _segment_sums( + d[key], + prompt_len=prompt_len, + gen_len=gen_len, + thinking_span_gen=thinking_span_gen, + sink_span_gen=sink_span_gen, + ) + out[key] = _with_fracs(sums) + out["thinking_span_gen"] = list(thinking_span_gen) if thinking_span_gen is not None else None + out["sink_span_gen"] = list(sink_span_gen) if sink_span_gen is not None else None + return out + + +def main() -> None: + parser = argparse.ArgumentParser("Summarize input/cot/output attribution mass from exp3 traces.") + parser.add_argument("--trace_root", type=str, default="exp/exp3/output/traces") + parser.add_argument("--dataset_tag", type=str, default="niah_mq_q2", help="Base tag; expands to _short_cot and _long_cot.") + parser.add_argument("--datasets", type=str, default=None, help="Comma-separated dataset names (overrides --dataset_tag expansion).") + parser.add_argument("--model", type=str, default=None, help="Model directory name under traces (default: auto if single).") + parser.add_argument("--run_tag", type=str, default=None, help="Run tag directory (default: auto pick newest/single).") + args = parser.parse_args() + + trace_root = Path(args.trace_root) + if not trace_root.exists(): + raise SystemExit(f"trace_root not found: {trace_root}") + + if args.datasets: + datasets = [x.strip() for x in str(args.datasets).split(",") if x.strip()] + else: + datasets = [f"{args.dataset_tag}_short_cot", f"{args.dataset_tag}_long_cot"] + + for ds in datasets: + run = _resolve_run(trace_root, dataset=ds, model=args.model, run_tag=args.run_tag) + records = list(_iter_manifest(run.run_dir)) + if not records: + raise SystemExit(f"Empty manifest: {run.run_dir/'manifest.jsonl'}") + for rec in records: + npz_path = run.run_dir / str(rec["file"]) + analysis = _analyze_npz(npz_path) + print( + json.dumps( + { + "dataset": run.dataset, + "model": run.model, + "run_dir": str(run.run_dir), + "example_idx": int(rec.get("example_idx", -1)), + **analysis, + }, + ensure_ascii=False, + ) + ) + + +if __name__ == "__main__": + main() + diff --git a/exp/exp3/run_exp.py b/exp/exp3/run_exp.py new file mode 100644 index 0000000000000000000000000000000000000000..f3592dd9c3d7d397a8a57ce959081d21e7d3b63f --- /dev/null +++ b/exp/exp3/run_exp.py @@ -0,0 +1,430 @@ +#!/usr/bin/env python3 +""" +Experiment 3 runner: long-vs-short CoT case study (AttnLRP hop0, Recovery@10%). + +This runner is intentionally minimal: + - Only reads two cached samples produced by exp/exp3/sample_and_filter.py: + _short_cot.jsonl + _long_cot.jsonl + - Only runs attribution method: attnlrp (hop0 path, aligned with exp2). + - Only computes token-level recovery (Recall@10%) using RULER needle_spans. + - Always saves per-sample trace artifacts under exp/exp3/output/traces/. + +All outputs are written under exp/exp3/output/ (configurable via --output_root). +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +import sys +import time +from itertools import islice +from pathlib import Path +from typing import Any, Dict, List, Optional, Tuple + + +def _early_set_cuda_visible_devices() -> None: + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("--cuda", type=str, default=None) + args, _ = parser.parse_known_args(sys.argv[1:]) + if args.cuda and "," in args.cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = args.cuda + + +_early_set_cuda_visible_devices() + +import numpy as np +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer, utils + +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + +import llm_attr +import llm_attr_eval +from exp.exp2 import dataset_utils as ds_utils + +utils.logging.set_verbosity_error() + + +def _sha1_text(text: str) -> str: + return hashlib.sha1(text.encode("utf-8")).hexdigest() + + +def _token_importance_vector(attr: torch.Tensor) -> np.ndarray: + w = torch.nan_to_num(attr.sum(0).to(dtype=torch.float32), nan=0.0).clamp(min=0.0) + return w.detach().cpu().numpy().astype(np.float32, copy=False) + + +def _trace_run_tag(*, neg_handling: str, norm_mode: str, total: int) -> str: + return f"attnlrp_neg{neg_handling}_norm{norm_mode}_recovery_{int(total)}ex" + + +def _build_sample_trace_payload( + example: ds_utils.CachedExample, + *, + seq_attr: torch.Tensor, + row_attr: torch.Tensor, + rec_attr: torch.Tensor, + prompt_len: int, + user_prompt_indices: Optional[List[int]], + gold_prompt_token_indices: Optional[List[int]], + recovery_scores: Optional[np.ndarray], + time_attr_s: Optional[float], + time_recovery_s: Optional[float], +) -> Dict[str, np.ndarray]: + gen_len = int(seq_attr.shape[0]) + + v_seq_all = _token_importance_vector(seq_attr) + v_row_all = _token_importance_vector(row_attr) + v_rec_all = _token_importance_vector(rec_attr) + + payload: Dict[str, np.ndarray] = { + "v_seq_all": v_seq_all, + "v_row_all": v_row_all, + "v_rec_all": v_rec_all, + "v_seq_prompt": v_seq_all[:prompt_len], + "v_row_prompt": v_row_all[:prompt_len], + "v_rec_prompt": v_rec_all[:prompt_len], + "prompt_len": np.asarray(int(prompt_len), dtype=np.int64), + "gen_len": np.asarray(int(gen_len), dtype=np.int64), + "indices_to_explain_gen": np.asarray(list(example.indices_to_explain or []), dtype=np.int64), + } + + if example.sink_span is not None: + payload["sink_span_gen"] = np.asarray(list(example.sink_span), dtype=np.int64) + if example.thinking_span is not None: + payload["thinking_span_gen"] = np.asarray(list(example.thinking_span), dtype=np.int64) + + if user_prompt_indices is not None: + payload["user_prompt_indices"] = np.asarray(list(user_prompt_indices), dtype=np.int64) + if gold_prompt_token_indices is not None: + payload["gold_prompt_token_indices"] = np.asarray(list(gold_prompt_token_indices), dtype=np.int64) + + if recovery_scores is not None: + payload["recovery_scores"] = np.asarray(recovery_scores, dtype=np.float64) + + if time_attr_s is not None: + payload["time_attr_s"] = np.asarray(float(time_attr_s), dtype=np.float64) + if time_recovery_s is not None: + payload["time_recovery_s"] = np.asarray(float(time_recovery_s), dtype=np.float64) + + return payload + + +def _write_sample_trace( + trace_dir: Path, + *, + example_idx: int, + prompt: str, + target: str, + payload: Dict[str, np.ndarray], + manifest_handle, + neg_handling: str, + norm_mode: str, + recovery_skipped_reason: Optional[str], +) -> None: + trace_dir.mkdir(parents=True, exist_ok=True) + npz_name = f"ex_{example_idx:06d}.npz" + npz_path = trace_dir / npz_name + np.savez_compressed(npz_path, **payload) + + prompt_len = int(np.asarray(payload.get("prompt_len", 0)).item()) + gen_len = int(np.asarray(payload.get("gen_len", 0)).item()) + record: Dict[str, Any] = { + "example_idx": int(example_idx), + "attr_func": "attnlrp", + "file": npz_name, + "prompt_sha1": _sha1_text(prompt), + "target_sha1": _sha1_text(target), + "prompt_len": prompt_len, + "gen_len": gen_len, + "indices_to_explain_gen": payload.get("indices_to_explain_gen").tolist() + if payload.get("indices_to_explain_gen") is not None + else None, + "sink_span_gen": payload.get("sink_span_gen").tolist() if payload.get("sink_span_gen") is not None else None, + "thinking_span_gen": payload.get("thinking_span_gen").tolist() + if payload.get("thinking_span_gen") is not None + else None, + "gold_prompt_token_indices": payload.get("gold_prompt_token_indices").tolist() + if payload.get("gold_prompt_token_indices") is not None + else None, + "recovery_scores": payload.get("recovery_scores").tolist() if payload.get("recovery_scores") is not None else None, + "recovery_skipped_reason": recovery_skipped_reason, + "time_attr_s": float(np.asarray(payload.get("time_attr_s")).item()) if payload.get("time_attr_s") is not None else None, + "time_recovery_s": float(np.asarray(payload.get("time_recovery_s")).item()) + if payload.get("time_recovery_s") is not None + else None, + "attnlrp_neg_handling": str(neg_handling), + "attnlrp_norm_mode": str(norm_mode), + } + manifest_handle.write(json.dumps(record, ensure_ascii=False) + "\n") + manifest_handle.flush() + + +def resolve_device(args) -> str: + if args.cuda is not None and "," in args.cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = args.cuda + return "auto" + if args.cuda is not None and str(args.cuda).strip(): + return f"cuda:{args.cuda}" if torch.cuda.is_available() else "cpu" + return f"cuda:{args.cuda_num}" if torch.cuda.is_available() else "cpu" + + +def load_model(model_name: str, device: str): + model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map="auto" if device == "auto" else {"": int(device.split(":")[1])} if device.startswith("cuda:") else None, + torch_dtype=torch.float16, + attn_implementation="eager", + ) + tokenizer = AutoTokenizer.from_pretrained(model_name) + tokenizer.pad_token = tokenizer.eos_token + model.eval() + return model, tokenizer + + +def _evaluate_one_dataset( + *, + dataset_name: str, + examples: List[ds_utils.CachedExample], + model, + tokenizer, + output_root: Path, + model_tag: str, + neg_handling: str, + norm_mode: str, + top_fraction: float, + num_examples: int, +) -> Tuple[np.ndarray, np.ndarray, float, int, int]: + llm_evaluator = llm_attr_eval.LLMAttributionEvaluator(model, tokenizer) + + results: List[np.ndarray] = [] + durations: List[float] = [] + skipped = 0 + + total = min(len(examples), int(num_examples)) + iterator = islice(examples, total) + + run_tag = _trace_run_tag(neg_handling=neg_handling, norm_mode=norm_mode, total=total) + trace_dir = output_root / "traces" / dataset_name / model_tag / run_tag + trace_dir.mkdir(parents=True, exist_ok=True) + manifest_handle = open(trace_dir / "manifest.jsonl", "w", encoding="utf-8") + + try: + for example_idx, ex in enumerate(iterator): + time_recovery_s: Optional[float] = None + recovery_scores: Optional[np.ndarray] = None + + needle_spans = (ex.metadata or {}).get("needle_spans") + if not isinstance(needle_spans, list) or not needle_spans: + raise SystemExit( + "exp3 recovery requires RULER samples with metadata.needle_spans; " + f"dataset={dataset_name} has missing/empty needle_spans." + ) + if ex.target is None: + raise SystemExit( + "exp3 recovery requires cached targets (CoT+answer) so row/rec attribution is well-defined. " + f"dataset={dataset_name} has target=None; run exp/exp3/sample_and_filter.py first." + ) + if not (isinstance(ex.indices_to_explain, list) and len(ex.indices_to_explain) == 2): + raise SystemExit( + "exp3 expects indices_to_explain=[start_tok,end_tok] in generation-token coordinates; " + f"dataset={dataset_name} has indices_to_explain={ex.indices_to_explain!r}; " + "run exp/exp3/sample_and_filter.py first." + ) + + gold_prompt = ds_utils.ruler_gold_prompt_token_indices(ex, tokenizer) + recovery_skip_reason: Optional[str] = None + + sample_start = time.perf_counter() + llm_attributor = llm_attr.LLMLRPAttribution(model, tokenizer) + attr_result = llm_attributor.calculate_attnlrp_ft_hop0( + ex.prompt, + target=ex.target, + sink_span=tuple(ex.sink_span) if ex.sink_span else None, + thinking_span=tuple(ex.thinking_span) if ex.thinking_span else None, + neg_handling=str(neg_handling), + norm_mode=str(norm_mode), + ) + seq_attr, row_attr, rec_attr = attr_result.get_all_token_attrs(list(ex.indices_to_explain)) + time_attr_s = time.perf_counter() - sample_start + durations.append(float(time_attr_s)) + + prompt_len = int(seq_attr.shape[1] - seq_attr.shape[0]) + if prompt_len <= 0: + recovery_skip_reason = "empty_prompt_len" + elif not gold_prompt: + recovery_skip_reason = "empty_gold_prompt" + else: + t2 = time.perf_counter() + recovery_scores = np.asarray( + [ + llm_evaluator.evaluate_attr_recovery( + a, + prompt_len=prompt_len, + gold_prompt_token_indices=gold_prompt, + top_fraction=top_fraction, + ) + for a in (seq_attr, row_attr, rec_attr) + ], + dtype=np.float64, + ) + time_recovery_s = time.perf_counter() - t2 + if np.isnan(recovery_scores).any(): + recovery_scores = None + recovery_skip_reason = "nan_recovery" + + if recovery_scores is None and recovery_skip_reason is not None: + skipped += 1 + elif recovery_scores is not None: + results.append(recovery_scores) + + payload = _build_sample_trace_payload( + ex, + seq_attr=seq_attr, + row_attr=row_attr, + rec_attr=rec_attr, + prompt_len=prompt_len, + user_prompt_indices=getattr(llm_attributor, "user_prompt_indices", None), + gold_prompt_token_indices=gold_prompt, + recovery_scores=recovery_scores, + time_attr_s=time_attr_s, + time_recovery_s=time_recovery_s, + ) + _write_sample_trace( + trace_dir, + example_idx=example_idx, + prompt=ex.prompt, + target=str(ex.target), + payload=payload, + manifest_handle=manifest_handle, + neg_handling=str(neg_handling), + norm_mode=str(norm_mode), + recovery_skipped_reason=recovery_skip_reason, + ) + finally: + try: + manifest_handle.close() + except Exception: + pass + + scores = np.stack(results, axis=0) if results else np.zeros((0, 3), dtype=np.float64) + used = int(scores.shape[0]) + mean = scores.mean(0) if used else np.full((3,), np.nan, dtype=np.float64) + std = scores.std(0) if used else np.full((3,), np.nan, dtype=np.float64) + avg_time = float(np.mean(durations)) if durations else 0.0 + return mean, std, avg_time, used, int(skipped) + + +def main() -> None: + parser = argparse.ArgumentParser("Experiment 3 runner (attnlrp hop0, recovery only).") + parser.add_argument("--dataset_tag", type=str, default="niah_mq_q2", help="Base tag for exp3 caches.") + parser.add_argument("--data_root", type=str, default="exp/exp3/data") + parser.add_argument("--output_root", type=str, default="exp/exp3/output") + parser.add_argument("--num_examples", type=int, default=1, help="How many examples to evaluate per dataset (default 1).") + parser.add_argument("--seed", type=int, default=42) + parser.add_argument("--model", type=str, default=None, help="HF repo id (required unless --model_path set).") + parser.add_argument("--model_path", type=str, default=None, help="Local path; overrides --model for loading.") + parser.add_argument("--cuda_num", type=int, default=0) + parser.add_argument("--cuda", type=str, default=None) + parser.add_argument("--top_fraction", type=float, default=0.1, help="Top fraction of prompt tokens used for recovery.") + parser.add_argument( + "--attnlrp_neg_handling", + type=str, + choices=["drop", "abs"], + default="drop", + help="AttnLRP hop0: how to handle negative values (drop=clamp>=0, abs=absolute value).", + ) + parser.add_argument( + "--attnlrp_norm_mode", + type=str, + choices=["norm", "no_norm"], + default="norm", + help="AttnLRP hop0: norm enables internal normalization; no_norm disables it.", + ) + args = parser.parse_args() + + if args.model_path: + model_name = args.model_path + elif args.model: + model_name = args.model + else: + raise SystemExit("Please set --model or --model_path.") + model_tag = args.model if args.model else Path(args.model_path).name + + device = resolve_device(args) + model, tokenizer = load_model(model_name, device) + + data_root = Path(args.data_root) + output_root = Path(args.output_root) + output_root.mkdir(parents=True, exist_ok=True) + + short_name = f"{args.dataset_tag}_short_cot" + long_name = f"{args.dataset_tag}_long_cot" + dataset_names = [short_name, long_name] + + summary_rows: List[Dict[str, Any]] = [] + + for ds_name in dataset_names: + cache_path = data_root / f"{ds_name}.jsonl" + if not cache_path.exists(): + raise SystemExit(f"Missing exp3 cache: {cache_path}. Run exp/exp3/sample_and_filter.py first.") + examples = ds_utils.load_cached(cache_path, sample=None, seed=args.seed) + + mean, std, avg_time, used, skipped = _evaluate_one_dataset( + dataset_name=ds_name, + examples=examples, + model=model, + tokenizer=tokenizer, + output_root=output_root, + model_tag=model_tag, + neg_handling=args.attnlrp_neg_handling, + norm_mode=args.attnlrp_norm_mode, + top_fraction=float(args.top_fraction), + num_examples=int(args.num_examples), + ) + + out_dir = output_root / "recovery" / ds_name / model_tag + out_dir.mkdir(parents=True, exist_ok=True) + filename = f"attnlrp_{int(args.num_examples)}_examples.csv" + with (out_dir / filename).open("w", encoding="utf-8") as f: + f.write("Method,Recovery@10%\n") + f.write(f"Seq Attr Recovery Mean,{mean[0]}\n") + f.write(f"Row Attr Recovery Mean,{mean[1]}\n") + f.write(f"Recursive Attr Recovery Mean,{mean[2]}\n") + f.write(f"Seq Attr Recovery Std,{std[0]}\n") + f.write(f"Row Attr Recovery Std,{std[1]}\n") + f.write(f"Recursive Attr Recovery Std,{std[2]}\n") + f.write(f"Examples Used,{used}\n") + f.write(f"Examples Skipped,{skipped}\n") + f.write(f"Avg Sample Time (s),{avg_time}\n") + + print(f"[{ds_name}] attnlrp -> {out_dir/filename} (used={used} skipped={skipped} avg {avg_time:.2f}s)") + summary_rows.append( + { + "dataset": ds_name, + "model": model_tag, + "neg_handling": args.attnlrp_neg_handling, + "norm_mode": args.attnlrp_norm_mode, + "seq_recovery@10%": float(mean[0]) if used else float("nan"), + "row_recovery@10%": float(mean[1]) if used else float("nan"), + "rec_recovery@10%": float(mean[2]) if used else float("nan"), + "used": int(used), + "skipped": int(skipped), + } + ) + + # Lightweight combined summary for quick comparison. + summary_path = output_root / "recovery" / f"summary_{model_tag}.json" + summary_path.parent.mkdir(parents=True, exist_ok=True) + summary_path.write_text(json.dumps(summary_rows, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + print(f"Wrote summary -> {summary_path}") + + +if __name__ == "__main__": + main() diff --git a/exp/exp3/sample_and_filter.py b/exp/exp3/sample_and_filter.py new file mode 100644 index 0000000000000000000000000000000000000000..216024b39ed952a624ca015d2bbe7025dcfa3180 --- /dev/null +++ b/exp/exp3/sample_and_filter.py @@ -0,0 +1,628 @@ +#!/usr/bin/env python3 +""" +Experiment 3 sampler: long-vs-short CoT case study (RULER niah_mq_q2, 1024). + +This script searches the raw RULER JSONL for a *single* prompt where BOTH: + - a short-CoT generation and a long-CoT generation + - follow the strict format: " + final \\box{...} answer" with + nothing after the box + - pass a judge model verifying the boxed answer matches the reference answer + - satisfy length constraints (short <= max_short_thinking_tokens, + long >= min_long_thinking_tokens) + +It writes two exp2-compatible cache JSONLs to exp/exp3/data/: + - _short_cot.jsonl + - _long_cot.jsonl + +Each JSONL line matches exp/exp2/dataset_utils.CachedExample schema and keeps +RULER metadata. The output caches are intended to be consumed by exp/exp3/run_exp.py. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +import sys +import time +import urllib.error +import urllib.request +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Dict, Iterable, List, Optional + +from tqdm import tqdm +from transformers import AutoTokenizer + +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + +from exp.exp2 import dataset_utils as ds_utils +from exp.exp2.dataset_utils import CachedExample, attach_spans_from_answer, split_boxed_generation + + +class RateLimitError(RuntimeError): + """Raised when API returns 429; carries a suggested wait time.""" + + def __init__(self, wait_seconds: float, detail: str) -> None: + super().__init__(detail) + self.wait_seconds = wait_seconds + + +SHORT_COT_SYSTEM_PROMPT = ( + "You are a reasoning assistant. " + "Before answering, engage in a brief chain of thought. " + "Process this freely and naturally without using specific headers or strict formatting. " + "When you reach the conclusion, wrap the entire final sentence containing the answer inside \\box{}. " + "Ensure the box wraps the **sentence** that naturally delivers the answer. " + "Do not add anything after the box." +) + +LONG_COT_SYSTEM_PROMPT = ( + "You are a careful reasoning assistant. " + "Before answering, engage in an extremely detailed and exhaustive chain of thought. " + "Do not skip any logical steps, even if they seem obvious. " + "Process this freely and naturally without using specific headers or strict formatting. " + "When you reach the conclusion, wrap the entire final sentence containing the answer inside \\box{}. " + "Ensure the box wraps the **sentence** that naturally delivers the answer. " + "Do not add anything after the box." +) + +JUDGE_SYSTEM_PROMPT = ( + "You verify whether the model's boxed answer matches the reference answer. " + "Reply strictly with True or False and nothing else." +) + + +def _sha1_text(text: str) -> str: + return hashlib.sha1(text.encode("utf-8")).hexdigest() + + +def call_chat_api( + api_base: str, + api_key: str, + model: str, + messages: List[Dict[str, str]], + *, + timeout: int, + max_tokens: int, + temperature: float, + cache_ttl: int, + cache_namespace: Optional[str], + rate_limit_delay: Optional[float] = None, +) -> str: + url = api_base.rstrip("/") + "/chat/completions" + payload: Dict[str, Any] = { + "model": model, + "messages": messages, + "max_tokens": max_tokens, + "temperature": temperature, + } + if cache_ttl > 0: + cache_obj: Dict[str, Any] = {"ttl": cache_ttl} + if cache_namespace: + cache_obj["namespace"] = cache_namespace + payload["cache"] = cache_obj + + data = json.dumps(payload).encode("utf-8") + headers = {"Content-Type": "application/json"} + if api_key: + headers["Authorization"] = f"Bearer {api_key}" + + req = urllib.request.Request(url, data=data, headers=headers, method="POST") + opener = urllib.request.build_opener(urllib.request.ProxyHandler({})) + try: + with opener.open(req, timeout=timeout) as resp: + resp_bytes = resp.read() + except urllib.error.HTTPError as e: + detail = e.read().decode("utf-8", errors="ignore") if hasattr(e, "read") else "" + if e.code == 429: + retry_after = None + if hasattr(e, "headers") and e.headers: + retry_after_header = e.headers.get("Retry-After") + if retry_after_header: + try: + retry_after = float(retry_after_header) + except ValueError: + retry_after = None + wait = retry_after or rate_limit_delay or 5.0 + raise RateLimitError(wait, f"API HTTP 429: {detail}") from e + raise RuntimeError(f"API HTTP error {e.code}: {detail}") from e + except urllib.error.URLError as e: + raise RuntimeError(f"API request failed: {e}") from e + + try: + response = json.loads(resp_bytes.decode("utf-8")) + except json.JSONDecodeError as e: + raise RuntimeError(f"Failed to decode API response: {resp_bytes!r}") from e + + choices = response.get("choices", []) + if not choices: + raise RuntimeError(f"Empty choices from API: {response}") + content = choices[0].get("message", {}).get("content", "") + if not content: + raise RuntimeError(f"Empty content from API: {response}") + return content.strip() + + +def _call_with_retries( + *, + api_base: str, + api_key: str, + model: str, + messages: List[Dict[str, str]], + timeout: int, + max_tokens: int, + temperature: float, + cache_ttl: int, + cache_namespace: Optional[str], + rate_limit_delay: float, + retries: int, + retry_delay: float, +) -> str: + for attempt in range(retries + 1): + try: + return call_chat_api( + api_base, + api_key, + model, + messages, + timeout=timeout, + max_tokens=max_tokens, + temperature=temperature, + cache_ttl=cache_ttl, + cache_namespace=cache_namespace, + rate_limit_delay=rate_limit_delay, + ) + except RateLimitError as e: + if attempt >= retries: + raise + time.sleep(e.wait_seconds) + except Exception: # noqa: BLE001 + if attempt >= retries: + raise + time.sleep(retry_delay) + raise RuntimeError("Unreachable") + + +def build_gen_messages(prompt: str, system_prompt: str) -> List[Dict[str, str]]: + return [ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": prompt}, + ] + + +def build_judge_messages(reference_answer: str, candidate_answer: str) -> List[Dict[str, str]]: + user = ( + "Decide if the model's boxed answer matches the reference answer.\n" + f"Reference answer: {reference_answer}\n" + f"Model boxed answer (only the content inside \\box{{}}): {candidate_answer}\n" + "Output only True if they are semantically consistent; otherwise output False." + ) + return [ + {"role": "system", "content": JUDGE_SYSTEM_PROMPT}, + {"role": "user", "content": user}, + ] + + +def parse_bool(text: str) -> bool: + first = text.strip().splitlines()[0].strip().lower() + if first in {"true", "yes"}: + return True + if first in {"false", "no"}: + return False + if "true" in first and "false" not in first: + return True + if "false" in first: + return False + raise ValueError(f"Cannot parse boolean from: {text!r}") + + +def write_cache(out_path: Path, examples: Iterable[CachedExample]) -> int: + out_path.parent.mkdir(parents=True, exist_ok=True) + count = 0 + with out_path.open("w", encoding="utf-8") as f: + for ex in examples: + obj: Dict[str, Any] = { + "prompt": ex.prompt, + "target": ex.target, + "indices_to_explain": ex.indices_to_explain, + "attr_mask_indices": ex.attr_mask_indices, + "sink_span": ex.sink_span, + "thinking_span": ex.thinking_span, + "metadata": ex.metadata, + } + f.write(json.dumps(obj, ensure_ascii=False) + "\n") + count += 1 + return count + + +@dataclass(frozen=True) +class AcceptedGeneration: + thinking_text: str + boxed_answer: str + target_text: str + thinking_tokens: int + generation_text: str + judge_response: str + + +def _infer_reference_answer(example: CachedExample) -> str: + meta = example.metadata or {} + ref = str(meta.get("reference_answer") or "").strip() + if ref: + return ref + outputs = meta.get("outputs") or [] + if isinstance(outputs, list) and outputs: + return ", ".join(str(x) for x in outputs) + tgt = str(example.target or "").strip() + return tgt + + +def _infer_dataset_tag(dataset_path: Path) -> str: + if dataset_path.name.endswith(".jsonl") and dataset_path.name != "validation.jsonl": + return dataset_path.stem + if dataset_path.name == "validation.jsonl": + return dataset_path.parent.name + return dataset_path.stem + + +def _count_tokens(tokenizer, text: str) -> int: + return int(len(tokenizer(text, add_special_tokens=False).input_ids)) + + +def _generate_one_style( + *, + prompt: str, + reference_answer: str, + tokenizer, + style: str, + system_prompt: str, + api_base: str, + api_key: str, + generator_model: str, + judge_model: str, + timeout: int, + max_tokens: int, + temperature: float, + cache_ttl: int, + cache_namespace: Optional[str], + rate_limit_delay: float, + retries: int, + retry_delay: float, + request_interval: float, + judge_interval: float, + min_long_thinking_tokens: int, + max_short_thinking_tokens: int, +) -> Optional[AcceptedGeneration]: + gen_messages = build_gen_messages(prompt, system_prompt) + generation = _call_with_retries( + api_base=api_base, + api_key=api_key, + model=generator_model, + messages=gen_messages, + timeout=timeout, + max_tokens=max_tokens, + temperature=temperature, + cache_ttl=cache_ttl, + cache_namespace=cache_namespace, + rate_limit_delay=rate_limit_delay, + retries=retries, + retry_delay=retry_delay, + ) + if request_interval > 0: + time.sleep(request_interval) + + parsed = split_boxed_generation(generation) + if not parsed: + return None + thinking_text, _boxed_segment, boxed_answer = parsed + thinking_tokens = _count_tokens(tokenizer, thinking_text) + + if style == "short": + if max_short_thinking_tokens > 0 and thinking_tokens > max_short_thinking_tokens: + return None + elif style == "long": + if min_long_thinking_tokens > 0 and thinking_tokens < min_long_thinking_tokens: + return None + else: + raise ValueError(f"Unsupported style: {style}") + + judge_messages = build_judge_messages(reference_answer, boxed_answer) + judge_resp = _call_with_retries( + api_base=api_base, + api_key=api_key, + model=judge_model, + messages=judge_messages, + timeout=timeout, + max_tokens=64, + temperature=0.0, + cache_ttl=cache_ttl, + cache_namespace=cache_namespace, + rate_limit_delay=rate_limit_delay, + retries=retries, + retry_delay=retry_delay, + ) + if judge_interval > 0: + time.sleep(judge_interval) + ok = parse_bool(judge_resp) + if not ok: + return None + + target_text = f"{thinking_text}\n{boxed_answer}" if thinking_text else boxed_answer + return AcceptedGeneration( + thinking_text=thinking_text, + boxed_answer=boxed_answer, + target_text=target_text, + thinking_tokens=thinking_tokens, + generation_text=generation, + judge_response=judge_resp, + ) + + +def main() -> None: + parser = argparse.ArgumentParser("Sample short-CoT and long-CoT cases for exp3 (independently).") + parser.add_argument( + "--dataset_path", + type=str, + default="data/ruler_multihop/1024/niah_mq_q2/validation.jsonl", + help="Raw RULER JSONL path (default: niah_mq_q2 1024 validation).", + ) + parser.add_argument("--dataset_tag", type=str, default=None, help="Output tag; default inferred from dataset_path.") + parser.add_argument( + "--max_pairs", + type=int, + default=1, + help="Deprecated alias for --max_short and --max_long (kept for convenience).", + ) + parser.add_argument("--max_short", type=int, default=None, help="How many short-CoT samples to keep (default: --max_pairs).") + parser.add_argument("--max_long", type=int, default=None, help="How many long-CoT samples to keep (default: --max_pairs).") + parser.add_argument("--max_raw_examples", type=int, default=None, help="Optional cap on raw examples to try.") + parser.add_argument("--seed", type=int, default=42) + parser.add_argument("--api_base", type=str, default="http://localhost:4000/v1", help="Chat API base URL.") + parser.add_argument("--api_key", type=str, default=None, help="API key; defaults to FLASHTRACE_API_KEY/OPENAI_API_KEY.") + parser.add_argument("--generator_model", type=str, default="qwen3-235b-a22b-2507") + parser.add_argument("--judge_model", type=str, default="deepseek-v3-1-terminus") + parser.add_argument("--api_timeout", type=int, default=300) + parser.add_argument("--api_temperature", type=float, default=0.0) + parser.add_argument("--api_cache_ttl", type=int, default=600) + parser.add_argument("--api_cache_namespace", type=str, default="flashtrace-exp3") + parser.add_argument("--retry_delay", type=float, default=2.0) + parser.add_argument("--retries", type=int, default=2, help="Additional retries on API failure.") + parser.add_argument("--request_interval", type=float, default=1.0, help="Sleep seconds between generation calls.") + parser.add_argument("--judge_interval", type=float, default=1.0, help="Sleep seconds between judge calls.") + parser.add_argument("--rate_limit_delay", type=float, default=5.0, help="Seconds to wait on HTTP 429 before retrying.") + parser.add_argument( + "--api_max_tokens_short", + type=int, + default=2048, + help="Max tokens for the short-CoT generation call.", + ) + parser.add_argument( + "--api_max_tokens_long", + type=int, + default=8192, + help="Max tokens for the long-CoT generation call.", + ) + parser.add_argument( + "--min_long_thinking_tokens", + type=int, + default=512, + help="Minimum tokenizer tokens required in the long-CoT thinking segment.", + ) + parser.add_argument( + "--max_short_thinking_tokens", + type=int, + default=256, + help="Maximum tokenizer tokens allowed in the short-CoT thinking segment.", + ) + parser.add_argument( + "--tokenizer_model", + type=str, + default=None, + help="Tokenizer path for span extraction & length constraints (default: generator_model).", + ) + parser.add_argument("--data_root", type=str, default="exp/exp3/data", help="Output directory for exp3 caches.") + parser.add_argument("--out_short", type=str, default=None, help="Optional explicit output path (short JSONL).") + parser.add_argument("--out_long", type=str, default=None, help="Optional explicit output path (long JSONL).") + args = parser.parse_args() + + api_key = args.api_key or os.environ.get("FLASHTRACE_API_KEY") or os.environ.get("OPENAI_API_KEY") + if not api_key: + raise SystemExit("Set --api_key or FLASHTRACE_API_KEY/OPENAI_API_KEY for API access.") + + dataset_path = Path(args.dataset_path) + if not dataset_path.exists(): + raise SystemExit(f"Dataset file not found: {dataset_path}") + dataset_tag = str(args.dataset_tag or _infer_dataset_tag(dataset_path)) + + tok_name = args.tokenizer_model or args.generator_model + tok_path = Path(tok_name) + if tok_path.exists(): + tokenizer = AutoTokenizer.from_pretrained(tok_path.as_posix(), local_files_only=True) + else: + tokenizer = AutoTokenizer.from_pretrained(tok_name) + tokenizer.pad_token = tokenizer.eos_token + + raw_examples = ds_utils.load_ruler(dataset_path, sample=None, seed=args.seed) + if not raw_examples: + raise SystemExit("No examples loaded from the RULER JSONL.") + + max_short = int(args.max_short) if args.max_short is not None else int(args.max_pairs) + max_long = int(args.max_long) if args.max_long is not None else int(args.max_pairs) + if max_short < 0 or max_long < 0: + raise SystemExit("--max_short/--max_long must be >= 0.") + + kept_short: List[CachedExample] = [] + kept_long: List[CachedExample] = [] + + total = len(raw_examples) + attempted = 0 + + for idx, ex in enumerate(tqdm(raw_examples, total=total, desc="Scanning raw RULER"), 1): + attempted = idx + if args.max_raw_examples is not None and idx > int(args.max_raw_examples): + break + if len(kept_short) >= max_short and len(kept_long) >= max_long: + break + + reference_answer = _infer_reference_answer(ex) + prompt = ex.prompt + + sample_id = _sha1_text(prompt) + base_meta = dict(ex.metadata or {}) + base_meta["reference_answer"] = reference_answer + base_meta["sample_id"] = sample_id + base_meta["pair_id"] = sample_id # backward-compatible name (may not be paired) + base_meta["source_dataset_path"] = str(dataset_path) + base_meta["prompt_sha1"] = sample_id + + if len(kept_short) < max_short: + short_gen = _generate_one_style( + prompt=prompt, + reference_answer=reference_answer, + tokenizer=tokenizer, + style="short", + system_prompt=SHORT_COT_SYSTEM_PROMPT, + api_base=args.api_base, + api_key=api_key, + generator_model=args.generator_model, + judge_model=args.judge_model, + timeout=args.api_timeout, + max_tokens=args.api_max_tokens_short, + temperature=args.api_temperature, + cache_ttl=args.api_cache_ttl, + cache_namespace=args.api_cache_namespace, + rate_limit_delay=args.rate_limit_delay, + retries=args.retries, + retry_delay=args.retry_delay, + request_interval=args.request_interval, + judge_interval=args.judge_interval, + min_long_thinking_tokens=args.min_long_thinking_tokens, + max_short_thinking_tokens=args.max_short_thinking_tokens, + ) + if short_gen is not None: + short_meta = dict(base_meta) + short_meta.update( + { + "cot_style": "short", + "generator_model": args.generator_model, + "judge_model": args.judge_model, + "judge_response": short_gen.judge_response, + "boxed_answer": short_gen.boxed_answer, + "thinking_tokens": int(short_gen.thinking_tokens), + } + ) + short_ex = CachedExample( + prompt=prompt, + target=short_gen.target_text, + indices_to_explain=None, + attr_mask_indices=ex.attr_mask_indices, + sink_span=None, + thinking_span=None, + metadata=short_meta, + ) + short_ex = attach_spans_from_answer(short_ex, tokenizer, short_gen.boxed_answer) + if isinstance(short_ex.sink_span, list) and len(short_ex.sink_span) == 2: + short_ex = CachedExample( + prompt=short_ex.prompt, + target=short_ex.target, + indices_to_explain=short_ex.sink_span, + attr_mask_indices=short_ex.attr_mask_indices, + sink_span=short_ex.sink_span, + thinking_span=short_ex.thinking_span, + metadata=short_ex.metadata, + ) + kept_short.append(short_ex) + print( + f"[kept short] raw_idx={idx}/{total} thinking_tokens={short_gen.thinking_tokens} " + f"sample_id={sample_id[:8]} kept={len(kept_short)}/{max_short}" + ) + + if len(kept_long) < max_long: + long_gen = _generate_one_style( + prompt=prompt, + reference_answer=reference_answer, + tokenizer=tokenizer, + style="long", + system_prompt=LONG_COT_SYSTEM_PROMPT, + api_base=args.api_base, + api_key=api_key, + generator_model=args.generator_model, + judge_model=args.judge_model, + timeout=args.api_timeout, + max_tokens=args.api_max_tokens_long, + temperature=args.api_temperature, + cache_ttl=args.api_cache_ttl, + cache_namespace=args.api_cache_namespace, + rate_limit_delay=args.rate_limit_delay, + retries=args.retries, + retry_delay=args.retry_delay, + request_interval=args.request_interval, + judge_interval=args.judge_interval, + min_long_thinking_tokens=args.min_long_thinking_tokens, + max_short_thinking_tokens=args.max_short_thinking_tokens, + ) + if long_gen is not None: + long_meta = dict(base_meta) + long_meta.update( + { + "cot_style": "long", + "generator_model": args.generator_model, + "judge_model": args.judge_model, + "judge_response": long_gen.judge_response, + "boxed_answer": long_gen.boxed_answer, + "thinking_tokens": int(long_gen.thinking_tokens), + } + ) + long_ex = CachedExample( + prompt=prompt, + target=long_gen.target_text, + indices_to_explain=None, + attr_mask_indices=ex.attr_mask_indices, + sink_span=None, + thinking_span=None, + metadata=long_meta, + ) + long_ex = attach_spans_from_answer(long_ex, tokenizer, long_gen.boxed_answer) + if isinstance(long_ex.sink_span, list) and len(long_ex.sink_span) == 2: + long_ex = CachedExample( + prompt=long_ex.prompt, + target=long_ex.target, + indices_to_explain=long_ex.sink_span, + attr_mask_indices=long_ex.attr_mask_indices, + sink_span=long_ex.sink_span, + thinking_span=long_ex.thinking_span, + metadata=long_ex.metadata, + ) + kept_long.append(long_ex) + print( + f"[kept long] raw_idx={idx}/{total} thinking_tokens={long_gen.thinking_tokens} " + f"sample_id={sample_id[:8]} kept={len(kept_long)}/{max_long}" + ) + + data_root = Path(args.data_root) + out_short = Path(args.out_short) if args.out_short else data_root / f"{dataset_tag}_short_cot.jsonl" + out_long = Path(args.out_long) if args.out_long else data_root / f"{dataset_tag}_long_cot.jsonl" + + n_short = write_cache(out_short, kept_short) + n_long = write_cache(out_long, kept_long) + print( + f"Wrote short={n_short} -> {out_short}\n" + f"Wrote long ={n_long} -> {out_long}\n" + f"Attempted {attempted} / {total}" + ) + + missing: List[str] = [] + if len(kept_short) < max_short: + missing.append(f"short({len(kept_short)}/{max_short})") + if len(kept_long) < max_long: + missing.append(f"long({len(kept_long)}/{max_long})") + if missing: + raise SystemExit(f"Could not find enough samples: {', '.join(missing)} (attempted {attempted} / {total}).") + + +if __name__ == "__main__": + main() diff --git a/exp/exp4/README.md b/exp/exp4/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a1ff2959206e77a16dc3aff00c53fbe3fa5c9594 --- /dev/null +++ b/exp/exp4/README.md @@ -0,0 +1,85 @@ +# FlashTrace ๅฎž้ชŒ 4๏ผˆAider ๅฝ’ๅ› ๅฟ ๅฎžๅบฆ / row-only๏ผ‰ + +ๆœฌ็›ฎๅฝ•ๆไพ› Aider ๆ•ฐๆฎ้›†ไธŠ็š„ token-level ๅฝ’ๅ› ๅฟ ๅฎžๅบฆ่ฏ„ๆต‹ๅทฅๅ…ท๏ผŒ**ๅช่พ“ๅ‡บ row ้ƒจๅˆ†็š„ RISE/MAS**๏ผŒไธไฟๅญ˜ๆ ทๆœฌ็บง traceใ€‚ + +่ฏ„ๆต‹่Œƒๅ›ด๏ผˆๅ›บๅฎš๏ผ‰๏ผš +- ๆ•ฐๆฎ้›†๏ผš`exp/exp4/data/aider.jsonl` +- ๆ–นๆณ•๏ผš + - `ifr_all_positions` + - `ifr_multi_hop_both`๏ผˆFlashTrace๏ผ‰ +- ๆŒ‡ๆ ‡๏ผš`RISE`ใ€`MAS`๏ผˆrow attribution only๏ผ‰ + +ไธป่ฆๆ–‡ไปถ๏ผš +- `run_exp.py`๏ผšๅฝ’ๅ›  + ๅฟ ๅฎžๅบฆ่ฏ„ๆต‹๏ผŒ่พ“ๅ‡บๅˆฐ `exp/exp4/output/` + +--- + +## ๆ•ฐๆฎๆ ผๅผ + +`exp/exp4/data/aider.jsonl` ๆฏ่กŒไธ€ไธช JSON๏ผŒๅฏนๅบ”ไธ€ไธชๆ ทๆœฌ๏ผš +- `input`๏ผšprompt๏ผˆ็›ดๆŽฅไฝœไธบ user prompt ๅ†…ๅฎน๏ผ‰ +- `output`๏ผštarget๏ผˆ็›ดๆŽฅไฝœไธบๆจกๅž‹็”Ÿๆˆๆ–‡ๆœฌ๏ผ›่„šๆœฌไผšๅ†…้ƒจ่ฟฝๅŠ  EOS ๅšๆ‰“ๅˆ†๏ผ‰ +- `length`๏ผšๆ•ฐๆฎ่‡ชๅธฆๅญ—ๆฎต๏ผˆ่„šๆœฌไธไพ่ต–๏ผŒไป…้€ไผ ๅˆฐ metadata๏ผ‰ + +่ฏดๆ˜Ž๏ผšAider ็š„ `output` ๅฝขๅฆ‚๏ผš +1) ็ฌฌไธ€่กŒ `xxx.py` +2) ็ฌฌไบŒ่กŒ opening fence ``` +3) ไธญ้—ดไธบไปฃ็  +4) ๆœ€ๅŽไธ€่กŒไธบ closing fence ``` + +--- + +## ๅฝ’ๅ› ไธŽ sink ้€‰ๆ‹ฉ + +่„šๆœฌๅฏนๆฏไธชๆ ทๆœฌ้ƒฝๅฐ† `input` ไฝœไธบ `prompt`๏ผŒๅฐ† `output` ไฝœไธบ `target`๏ผˆไธๅš้‡ๆ–ฐ็”Ÿๆˆ๏ผ‰๏ผŒๅนถๅœจๅฝ’ๅ› ็ป“ๆžœไธŠ้€‰ๆ‹ฉไธๅŒ็š„ sink๏ผˆ`indices_to_explain=[start_tok,end_tok]`๏ผŒๅ‡ๅŸบไบŽ `tokenizer(target, add_special_tokens=False)` ็š„ token span๏ผ›ไธๅซ EOS๏ผ‰ใ€‚ + +### `ifr_all_positions`๏ผˆ่พ“ๅ‡บไธคไธช sink๏ผ‰ + +- `last_line`๏ผšๅ– `output` ไธญ **closing fence ไน‹ๅ‰ๆœ€ๅŽไธ€ไธชโ€œ้ž็ฉบไธ”้ž ```โ€่กŒ**๏ผŒๅนถๅฐ†่ฏฅ่กŒ็š„ๅญ—็ฌฆ span ๆ˜ ๅฐ„ๅˆฐ token span๏ผ›่‹ฅๆ— ๆณ•่งฃๆžๅˆ™ๅ›ž้€€ไธบ `full_output`ใ€‚ +- `last_token`๏ผšๅ– `last_line` ็š„ๆœ€ๅŽไธ€ไธช token๏ผˆๅ•็‚น span `[end,end]`๏ผ‰ใ€‚ + +ๆณจๆ„๏ผš่„šๆœฌไผšๅฏนๅŒไธ€ไธชๆ ทๆœฌๅช่ฎก็ฎ—ไธ€ๆฌก `ifr_all_positions` ็š„ๅฝ’ๅ› ็Ÿฉ้˜ต๏ผŒ็„ถๅŽๅˆ†ๅˆซๅœจไธคไธช sink ไธŠๅ– row attribution ๅนถ่ฎก็ฎ—ๅฟ ๅฎžๅบฆใ€‚ + +### `ifr_multi_hop_both`๏ผˆFlashTrace๏ผŒๅช่พ“ๅ‡บไธ€ไธช sink๏ผ‰ + +- `full_output`๏ผš็”จๅฎŒๆ•ด `output` ไฝœไธบ sink๏ผˆtoken span `[0, n_tok-1]`๏ผ‰ใ€‚ +- ๅฟ ๅฎžๅบฆๆ‰ฐๅŠจไพงไผšๆฒฟ็”จ exp2 ็š„ๅ่ฎฎ๏ผšๅฏน prompt-side ไผš่ทณ่ฟ‡ stop tokens๏ผˆ็”ฑ `ft_ifr_improve.py` ็š„ stop-token ้…็ฝฎๅ†ณๅฎš๏ผ‰ใ€‚ + +--- + +## ๆŒ‡ๆ ‡่พ“ๅ‡บ๏ผˆrow-only๏ผ‰ + +่พ“ๅ‡บ CSV ไป…ๅŒ…ๅซ row attribution ็š„ `RISE/MAS` ่šๅˆ็ปŸ่ฎก๏ผš +- `Method,Sink,Row_RISE_Mean,Row_RISE_Std,Row_MAS_Mean,Row_MAS_Std,Used,Skipped,Avg_Sample_Time_s` + +่พ“ๅ‡บ่ทฏๅพ„๏ผš +- `exp/exp4/output/faithfulness/aider//row_only__examples.csv` + +ๅ…ถไธญ `` ไผ˜ๅ…ˆๅ– `--model`๏ผŒๅฆๅˆ™ๅ– `--model_path` ็š„็›ฎๅฝ•ๅใ€‚ + +--- + +## ไฝฟ็”จ่ฏดๆ˜Ž + +ๆŽจ่ไปŽ repo root ่ฟ่กŒ๏ผˆไฟ่ฏ็›ธๅฏน่ทฏๅพ„ๅฏ็”จ๏ผ‰๏ผš + +```bash +python exp/exp4/run_exp.py \ + --data_path exp/exp4/data/aider.jsonl \ + --output_root exp/exp4/output \ + --model qwen-8B \ + --model_path /opt/share/models/Qwen/Qwen3-8B/ \ + --cuda 2,3,4,5,6,7 \ + --num_examples 100 \ + --n_hops 1 \ + --k 20 +``` + +ๅธธ็”จๅ‚ๆ•ฐ๏ผš +- `--model_path` / `--model`๏ผšๆœฌๅœฐๆจกๅž‹่ทฏๅพ„ๆˆ– HF repo id๏ผˆ่‡ณๅฐ‘ๆไพ›ๅ…ถไธ€๏ผ‰ +- `--tokenizer_path`๏ผšๅฏ้€‰๏ผ›ไธๆไพ›ๅˆ™้ป˜่ฎคๅค็”จๆจกๅž‹่ทฏๅพ„/id +- `--cuda`๏ผšๆ”ฏๆŒ `0`๏ผˆๅ•ๅก๏ผ‰ๆˆ– `0,1,2`๏ผˆๅคšๅก๏ผŒๅ†…้ƒจไผš่ฎพ็ฝฎ `CUDA_VISIBLE_DEVICES` ๅนถ็”จ `device_map=auto`๏ผ‰ +- `--num_examples`๏ผš่ฏ„ๆต‹ๅ‰ N ๆก๏ผˆๆŒ‰ๆ–‡ไปถ้กบๅบ๏ผ›`--seed` ้ข„็•™๏ผŒๅฝ“ๅ‰ไธๅš้šๆœบๆŠฝๆ ท๏ผ‰ +- `--n_hops`๏ผšFlashTrace๏ผˆ`ifr_multi_hop_both`๏ผ‰็š„ hop ๆ•ฐ +- `--k`๏ผšMAS/RISE ็š„ๆ‰ฐๅŠจๆญฅๆ•ฐ +- `--chunk_tokens` / `--sink_chunk_tokens`๏ผšIFR ่ฎก็ฎ—็š„ chunk ๅ‚ๆ•ฐ๏ผˆไธ€่ˆฌไฟๆŒ้ป˜่ฎค๏ผ‰ diff --git a/exp/exp4/run_exp.py b/exp/exp4/run_exp.py new file mode 100644 index 0000000000000000000000000000000000000000..9c50b93d5f3fbcdf081b6595bca0778cde265c8b --- /dev/null +++ b/exp/exp4/run_exp.py @@ -0,0 +1,487 @@ +#!/usr/bin/env python3 +""" +Experiment 4 runner: Aider token-level attribution faithfulness. + +Evaluates only: +- IFR: ifr_all_positions + - sink = last meaningful code line (excluding fences) + - sink = last token of that code line +- FlashTrace: ifr_multi_hop_both + - sink = full output (excluding appended EOS) + +Outputs only row-level faithfulness scores (RISE, MAS). No sample-level traces. +""" + +from __future__ import annotations + +import argparse +import json +import os +import sys +import time +from dataclasses import dataclass +from itertools import islice +from pathlib import Path +from typing import Any, Dict, List, Optional, Sequence, Tuple + + +def _early_set_cuda_visible_devices() -> None: + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument("--cuda", type=str, default=None) + args, _ = parser.parse_known_args(sys.argv[1:]) + if args.cuda and "," in args.cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = args.cuda + + +_early_set_cuda_visible_devices() + +import numpy as np +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer, utils + +# Ensure repo root on path for `import llm_attr`, `import ft_ifr_improve`, etc. +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + +import ft_ifr_improve +import llm_attr +import llm_attr_eval + +utils.logging.set_verbosity_error() + + +@dataclass(frozen=True) +class AiderExample: + prompt: str + target: str + metadata: Dict[str, Any] + + +def _read_jsonl(path: Path) -> List[Dict[str, Any]]: + rows: List[Dict[str, Any]] = [] + with path.open("r", encoding="utf-8") as f: + for line in f: + if not line.strip(): + continue + rows.append(json.loads(line)) + return rows + + +def load_aider(path: Path) -> List[AiderExample]: + rows = _read_jsonl(path) + examples: List[AiderExample] = [] + for row in rows: + prompt = str(row.get("input") or "") + target = str(row.get("output") or "") + examples.append(AiderExample(prompt=prompt, target=target, metadata={"length": row.get("length")})) + return examples + + +def _token_span_full_output(tokenizer, target: str) -> List[int]: + ids = tokenizer(target, add_special_tokens=False).input_ids + if not ids: + return [0, 0] + return [0, int(len(ids) - 1)] + + +def _last_meaningful_code_line_char_span(target: str) -> Optional[Tuple[int, int]]: + lines = target.splitlines(keepends=True) + pos = 0 + spans: List[Tuple[int, int, str]] = [] + for line in lines: + start = pos + pos += len(line) + spans.append((start, pos, line)) + + for start, end, line in reversed(spans): + stripped = line.strip() + if not stripped: + continue + if stripped.startswith("```"): + continue + if start == 0 and stripped.endswith(".py"): + return None + + line_no_nl = line.rstrip("\r\n") + end_no_nl = start + len(line_no_nl) + if end_no_nl <= start: + continue + return start, end_no_nl + + return None + + +def _char_span_to_token_span(tokenizer, text: str, span: Tuple[int, int]) -> Optional[List[int]]: + start_char, end_char = int(span[0]), int(span[1]) + if end_char <= start_char: + return None + + enc = tokenizer(text, add_special_tokens=False, return_offsets_mapping=True) + offsets = enc.get("offset_mapping") + if offsets is None: + raise ValueError("Tokenizer does not provide offset_mapping; cannot map char spans to tokens.") + + tok_indices: List[int] = [] + for idx, off in enumerate(offsets): + if off is None: + continue + s, e = int(off[0]), int(off[1]) + if s < end_char and e > start_char: + tok_indices.append(int(idx)) + if not tok_indices: + return None + return [min(tok_indices), max(tok_indices)] + + +def _last_meaningful_code_line_token_span(tokenizer, target: str) -> List[int]: + full_span = _token_span_full_output(tokenizer, target) + span_chars = _last_meaningful_code_line_char_span(target) + if span_chars is None: + return full_span + + span_toks = _char_span_to_token_span(tokenizer, target, span_chars) + if span_toks is None: + return full_span + + span_toks[0] = max(int(span_toks[0]), int(full_span[0])) + span_toks[1] = min(int(span_toks[1]), int(full_span[1])) + if span_toks[1] < span_toks[0]: + return full_span + return span_toks + + +def _last_token_span(token_span: Sequence[int]) -> List[int]: + if not (isinstance(token_span, Sequence) and len(token_span) == 2): + return [0, 0] + end = int(token_span[1]) + return [end, end] + + +def resolve_device(args) -> str: + if args.cuda is not None and "," in args.cuda: + os.environ["CUDA_VISIBLE_DEVICES"] = args.cuda + return "auto" + if args.cuda is not None and args.cuda.strip(): + return f"cuda:{args.cuda}" if torch.cuda.is_available() else "cpu" + return f"cuda:{args.cuda_num}" if torch.cuda.is_available() else "cpu" + + +def load_model_and_tokenizer(args) -> tuple[Any, Any]: + model_id = args.model_path or args.model + if not model_id: + raise SystemExit("Provide --model_path (local) or --model (HF repo id).") + + tokenizer_id = args.tokenizer_path or model_id + device = resolve_device(args) + + model = AutoModelForCausalLM.from_pretrained( + model_id, + device_map="auto" if device == "auto" else {"": int(device.split(":")[1])} if device.startswith("cuda:") else None, + torch_dtype=torch.float16, + attn_implementation="eager", + ) + tokenizer = AutoTokenizer.from_pretrained(tokenizer_id) + if tokenizer.pad_token_id is None and tokenizer.eos_token_id is not None: + tokenizer.pad_token = tokenizer.eos_token + model.eval() + return model, tokenizer + + +def _faithfulness_test_with_user_prompt_indices( + llm_evaluator: llm_attr_eval.LLMAttributionEvaluator, + attribution: torch.Tensor, + prompt: str, + generation: str, + *, + user_prompt_indices: List[int], + k: int = 20, +) -> Tuple[float, float, float]: + def auc(arr: np.ndarray) -> float: + return (arr.sum() - arr[0] / 2 - arr[-1] / 2) / max(1, (arr.shape[0] - 1)) + + pad_token_id = llm_evaluator._ensure_pad_token_id() + + user_prompt = " " + prompt + formatted_prompt = llm_evaluator.format_prompt(user_prompt) + formatted_ids = llm_evaluator.tokenizer(formatted_prompt, return_tensors="pt", add_special_tokens=False).input_ids + + prompt_ids = formatted_ids.to(llm_evaluator.device) + prompt_ids_perturbed = prompt_ids.clone() + generation_ids = llm_evaluator.tokenizer( + generation + llm_evaluator.tokenizer.eos_token, + return_tensors="pt", + add_special_tokens=False, + ).input_ids.to(llm_evaluator.device) + + attr_cpu = attribution.detach().cpu() + w = attr_cpu.sum(0) + sorted_attr_indices = torch.argsort(w, descending=True) + attr_sum = float(w.sum().item()) + + P = int(w.numel()) + if len(user_prompt_indices) != P: + raise ValueError( + "user_prompt_indices length does not match prompt-side attribution length: " + f"indices P={len(user_prompt_indices)}, attr P={P}." + ) + if P == 0: + return 0.0, 0.0, 0.0 + + if max(user_prompt_indices) >= int(prompt_ids_perturbed.shape[1]): + raise ValueError("user_prompt_indices contains an out-of-bounds index for formatted prompt ids.") + + steps = int(k) if k is not None else 0 + if steps <= 0: + steps = 1 + steps = min(steps, P) + + scores = np.zeros(steps + 1, dtype=np.float64) + density = np.zeros(steps + 1, dtype=np.float64) + + scores[0] = ( + llm_evaluator.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + ) + density[0] = 1.0 + + if attr_sum <= 0: + density = np.linspace(1.0, 0.0, steps + 1) + + base = P // steps + remainder = P % steps + start = 0 + for step in range(steps): + size = base + (1 if step < remainder else 0) + group = sorted_attr_indices[start : start + size] + start += size + + for idx in group: + j = int(idx.item()) + abs_pos = int(user_prompt_indices[j]) + prompt_ids_perturbed[0, abs_pos] = pad_token_id + scores[step + 1] = ( + llm_evaluator.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + ) + if attr_sum > 0: + dec = float(w.index_select(0, group).sum().item()) / attr_sum + density[step + 1] = density[step] - dec + + min_normalized_pred = 1.0 + normalized_model_response = scores.copy() + for i in range(len(scores)): + normalized_pred = (normalized_model_response[i] - scores[-1]) / (abs(scores[0] - scores[-1])) + normalized_pred = np.clip(normalized_pred, 0.0, 1.0) + min_normalized_pred = min(min_normalized_pred, normalized_pred) + normalized_model_response[i] = min_normalized_pred + + alignment_penalty = np.abs(normalized_model_response - density) + corrected_scores = normalized_model_response + alignment_penalty + corrected_scores = corrected_scores.clip(0.0, 1.0) + corrected_scores = (corrected_scores - np.min(corrected_scores)) / (np.max(corrected_scores) - np.min(corrected_scores)) + + if np.isnan(corrected_scores).any(): + corrected_scores = np.linspace(1.0, 0.0, len(scores)) + + return auc(normalized_model_response), auc(corrected_scores), auc(normalized_model_response + alignment_penalty) + + +def _row_faithfulness_scores( + *, + llm_evaluator: llm_attr_eval.LLMAttributionEvaluator, + attribution_prompt: torch.Tensor, + prompt: str, + generation: str, + user_prompt_indices: Optional[List[int]], + keep_prompt_token_indices: Optional[Sequence[int]] = None, + k: int = 20, +) -> Tuple[float, float]: + if keep_prompt_token_indices is not None: + rise, mas, _ = ft_ifr_improve.faithfulness_test_skip_tokens( + llm_evaluator, + attribution_prompt, + prompt, + generation, + keep_prompt_token_indices=keep_prompt_token_indices, + user_prompt_indices=user_prompt_indices, + k=int(k), + ) + return float(rise), float(mas) + if user_prompt_indices is not None: + rise, mas, _ = _faithfulness_test_with_user_prompt_indices( + llm_evaluator, + attribution_prompt, + prompt, + generation, + user_prompt_indices=user_prompt_indices, + k=int(k), + ) + return float(rise), float(mas) + + rise, mas, _ = llm_evaluator.faithfulness_test(attribution_prompt, prompt, generation, k=int(k)) + return float(rise), float(mas) + + +def _model_tag(args) -> str: + if args.model: + return str(args.model) + if args.model_path: + return Path(args.model_path).name + return "model" + + +def main() -> None: + parser = argparse.ArgumentParser("Experiment 4 runner: aider faithfulness (row-only).") + parser.add_argument("--data_path", type=str, default="exp/exp4/data/aider.jsonl") + parser.add_argument("--output_root", type=str, default="exp/exp4/output") + parser.add_argument("--model", type=str, default=None, help="HF repo id (required unless --model_path set).") + parser.add_argument("--model_path", type=str, default=None, help="Local path; overrides --model for loading.") + parser.add_argument("--tokenizer_path", type=str, default=None, help="Optional tokenizer path/id (defaults to model).") + parser.add_argument("--cuda", type=str, default=None) + parser.add_argument("--cuda_num", type=int, default=0) + parser.add_argument("--num_examples", type=int, default=100) + parser.add_argument("--seed", type=int, default=42, help="Reserved for future use; exp4 runs in file order.") + parser.add_argument("--chunk_tokens", type=int, default=128) + parser.add_argument("--sink_chunk_tokens", type=int, default=32) + parser.add_argument("--n_hops", type=int, default=3) + parser.add_argument("--k", type=int, default=20, help="Perturbation steps for MAS/RISE.") + args = parser.parse_args() + + data_path = Path(args.data_path) + if not data_path.exists(): + raise SystemExit(f"Missing Aider JSONL: {data_path}") + + model, tokenizer = load_model_and_tokenizer(args) + llm_evaluator = llm_attr_eval.LLMAttributionEvaluator(model, tokenizer) + + examples = load_aider(data_path) + total = min(len(examples), int(args.num_examples)) + iterator = islice(examples, total) + + ifr = llm_attr.LLMIFRAttribution( + model, + tokenizer, + chunk_tokens=int(args.chunk_tokens), + sink_chunk_tokens=int(args.sink_chunk_tokens), + ) + flashtrace = ft_ifr_improve.LLMIFRAttributionBoth( + model, + tokenizer, + chunk_tokens=int(args.chunk_tokens), + sink_chunk_tokens=int(args.sink_chunk_tokens), + ) + + results: Dict[Tuple[str, str], List[Tuple[float, float]]] = { + ("ifr_all_positions", "last_line"): [], + ("ifr_all_positions", "last_token"): [], + ("ifr_multi_hop_both", "full_output"): [], + } + skipped: Dict[Tuple[str, str], int] = {k: 0 for k in results} + sample_times: Dict[Tuple[str, str], List[float]] = {k: [] for k in results} + + for example_idx, ex in enumerate(iterator): + prompt = ex.prompt + target = ex.target + + full_span = _token_span_full_output(tokenizer, target) + last_line_span = _last_meaningful_code_line_token_span(tokenizer, target) + last_token_span = _last_token_span(last_line_span) + + attr_all = None + attr_all_time_s = 0.0 + user_prompt_indices_all: Optional[List[int]] = None + prompt_len_all = 0 + try: + t_attr = time.perf_counter() + attr_all = ifr.calculate_ifr_for_all_positions(prompt, target=target) + attr_all_time_s = float(time.perf_counter() - t_attr) + user_prompt_indices_all = list(getattr(ifr, "user_prompt_indices", []) or []) + prompt_len_all = int(len(attr_all.prompt_tokens)) + except Exception as exc: + skipped[("ifr_all_positions", "last_line")] += 1 + skipped[("ifr_all_positions", "last_token")] += 1 + print(f"[warn] ifr_all_positions attribution failed ex={example_idx}: {exc}") + + if attr_all is not None and user_prompt_indices_all is not None and prompt_len_all >= 0: + for sink_name, span in (("last_line", last_line_span), ("last_token", last_token_span)): + key = ("ifr_all_positions", sink_name) + try: + t_faith = time.perf_counter() + row = attr_all.get_all_token_attrs(list(span))[1] + rise, mas = _row_faithfulness_scores( + llm_evaluator=llm_evaluator, + attribution_prompt=row[:, :prompt_len_all], + prompt=prompt, + generation=target, + user_prompt_indices=user_prompt_indices_all, + k=int(args.k), + ) + faith_time_s = float(time.perf_counter() - t_faith) + results[key].append((rise, mas)) + sample_times[key].append(attr_all_time_s + faith_time_s) + except Exception as exc: + skipped[key] += 1 + print(f"[warn] ifr_all_positions {sink_name} failed ex={example_idx}: {exc}") + + try: + t_attr = time.perf_counter() + attr_ft = flashtrace.calculate_ifr_multi_hop_both( + prompt, + target=target, + sink_span=None, + thinking_span=None, + n_hops=int(args.n_hops), + ) + attr_ft_time_s = float(time.perf_counter() - t_attr) + user_prompt_indices_ft = list(getattr(flashtrace, "user_prompt_indices", []) or []) + prompt_len_ft = int(len(attr_ft.prompt_tokens)) + keep_prompt_token_indices = ft_ifr_improve.keep_token_indices(list(attr_ft.prompt_tokens)) + + t_faith = time.perf_counter() + row_full = attr_ft.get_all_token_attrs(full_span)[1] + rise, mas = _row_faithfulness_scores( + llm_evaluator=llm_evaluator, + attribution_prompt=row_full[:, :prompt_len_ft], + prompt=prompt, + generation=target, + user_prompt_indices=user_prompt_indices_ft, + keep_prompt_token_indices=keep_prompt_token_indices, + k=int(args.k), + ) + faith_time_s = float(time.perf_counter() - t_faith) + results[("ifr_multi_hop_both", "full_output")].append((rise, mas)) + sample_times[("ifr_multi_hop_both", "full_output")].append(attr_ft_time_s + faith_time_s) + except Exception as exc: + skipped[("ifr_multi_hop_both", "full_output")] += 1 + print(f"[warn] ifr_multi_hop_both failed ex={example_idx}: {exc}") + + model_tag = _model_tag(args) + out_dir = Path(args.output_root) / "faithfulness" / "aider" / model_tag + out_dir.mkdir(parents=True, exist_ok=True) + out_path = out_dir / f"row_only_{total}_examples.csv" + + with out_path.open("w", encoding="utf-8") as f: + f.write("Method,Sink,Row_RISE_Mean,Row_RISE_Std,Row_MAS_Mean,Row_MAS_Std,Used,Skipped,Avg_Sample_Time_s\n") + for (method, sink), vals in results.items(): + arr = np.asarray(vals, dtype=np.float64) + used = int(arr.shape[0]) + if used == 0: + rise_mean = float("nan") + rise_std = float("nan") + mas_mean = float("nan") + mas_std = float("nan") + else: + rise_mean = float(arr[:, 0].mean()) + rise_std = float(arr[:, 0].std()) + mas_mean = float(arr[:, 1].mean()) + mas_std = float(arr[:, 1].std()) + times = sample_times.get((method, sink)) or [] + avg_time = float(np.mean(times)) if times else 0.0 + f.write( + f"{method},{sink},{rise_mean},{rise_std},{mas_mean},{mas_std},{used},{int(skipped[(method, sink)])},{avg_time}\n" + ) + + print(f"[done] wrote {out_path}") + + +if __name__ == "__main__": + main() diff --git a/exp/exp5/README.md b/exp/exp5/README.md new file mode 100644 index 0000000000000000000000000000000000000000..dacdda687d20e45aa4a0dc3feca84963d603bf2b --- /dev/null +++ b/exp/exp5/README.md @@ -0,0 +1,119 @@ +# FlashTrace ๅฎž้ชŒ 5๏ผš่ทจๆจกๅž‹๏ผˆQwen โ†’ Llama๏ผ‰token-span ๆ˜ ๅฐ„ + +## ่ƒŒๆ™ฏ๏ผšไธบไป€ไนˆ้œ€่ฆๆ˜ ๅฐ„ + +`exp/exp2/run_exp.py` ็š„ๅฝ’ๅ› ไธŽ่ฏ„ไผฐๆ˜ฏไธฅๆ ผ **token-level** ็š„๏ผŒๅนถไธ”ไพ่ต–็ผ“ๅญ˜ๆ•ฐๆฎไธญ็š„ token-span ๅญ—ๆฎต๏ผš + +- `indices_to_explain = [start_tok, end_tok]`๏ผˆgeneration token indices๏ผŒ้—ญๅŒบ้—ด๏ผ‰ +- `sink_span` / `thinking_span`๏ผˆๅŒๆ ทๆ˜ฏ generation token spans๏ผ‰ + +่ฟ™ไบ› span ๅœจ็”Ÿๆˆ็ผ“ๅญ˜๏ผˆ`exp/exp2/sample_and_filter.py`ใ€`exp/exp2/map_math_mine_to_exp2_cache.py`๏ผ‰ๆ—ถๆ˜ฏ็”จๆŸไธช tokenizer ่ฎก็ฎ—ๅนถๅ†™ๆญป็š„๏ผˆ้€šๅธธๆ˜ฏ `Qwen3-8B` ็š„ tokenizer๏ผ‰ใ€‚ + +ๅฝ“ไฝ ๅˆ‡ๆขๅˆฐๆ–ฐๆจกๅž‹๏ผˆไพ‹ๅฆ‚ `Llama-3.1-8B-Instruct`๏ผ‰ๆ—ถ๏ผŒ**tokenizer ไธๅŒ**๏ผŒ`target` ็š„ tokenization ้•ฟๅบฆ/่พน็•Œไผšๅ˜ๅŒ–๏ผŒๅฏผ่‡ดๆ—ง็š„ span ๅœจๆ–ฐ tokenizer ไธ‹็ปๅธธ่ถŠ็•Œ๏ผŒไปŽ่€Œ่ฎฉ exp2 ๅœจๅฝ’ๅ› ้˜ถๆฎต็›ดๆŽฅๆŠฅ้”™๏ผˆ`IndexError: end_tok out of range`๏ผ‰ใ€‚ + +## ่งฃๅ†ณๆ–นๆกˆ๏ผšexp5 ๆ˜ ๅฐ„่„šๆœฌ + +`exp/exp5/map_exp2_cache_token_spans.py` ๅฐ† exp2 ็ผ“ๅญ˜้‡Œ็š„ๆ—ง token-span ไปŽๆ—ง tokenizer๏ผˆ้ป˜่ฎค `Qwen3-8B`๏ผ‰ๆ˜ ๅฐ„ๅˆฐๆ–ฐ tokenizer๏ผˆ้ป˜่ฎค `Llama-3.1-8B-Instruct`๏ผ‰๏ผŒๅนถ่พ“ๅ‡บๅˆฐ๏ผš + +`exp/exp5/data/<ๅŒๅๆ•ฐๆฎ้›†>.jsonl` + +ๆ˜ ๅฐ„็ญ–็•ฅ๏ผˆ้ป˜่ฎค๏ผ‰๏ผš +1) ็”จๆ—ง tokenizer ๅฏน `target` ๅš `return_offsets_mapping=True` +2) ๆŠŠๆ—ง็š„ token-span ่ฝฌๆˆ `target` ็š„ๅญ—็ฌฆๅŒบ้—ด +3) ็”จๆ–ฐ tokenizer ๅฏนๅŒไธ€ไธช `target` ๅš offsets๏ผŒๅ†ๆŠŠๅญ—็ฌฆๅŒบ้—ดๆ˜ ๅฐ„ๅ›žๆ–ฐ็š„ token-span + +ๅฆ‚้‡ๆž็ซฏๆƒ…ๅ†ต๏ผˆ็ผ“ๅญ˜ๅนถ้ž็”ฑ้ข„ๆœŸๆ—ง tokenizer ไบง็”Ÿ๏ผ‰๏ผŒๅฏๅฏ็”จ `--allow_fallback_answer`๏ผŒ็”จ `metadata.boxed_answer`๏ผˆๆˆ– `reference_answer`๏ผ‰ๅœจๆ–ฐ tokenizer ไธ‹้‡ๆ–ฐๅฎšไฝ span ไฝœไธบๅ…œๅบ•ใ€‚ + +--- + +## Step 1๏ผšๆŠŠ exp2 ๆ•ฐๆฎ้›†็ผ“ๅญ˜ๆ˜ ๅฐ„ๅˆฐ exp5/data + +ๆŽจ่ไฝฟ็”จไป“ๅบ“็š„ venv๏ผš + +```bash +.venv/bin/python exp/exp5/map_exp2_cache_token_spans.py \ + --in_jsonl exp/exp2/data/niah_mq_q2.jsonl \ + --out_dir exp/exp5/data \ + --old_tokenizer_model /opt/share/models/Qwen/Qwen3-8B \ + --new_tokenizer_model /opt/share/models/meta-llama/Llama-3.1-8B-Instruct +``` + +ไธ€ๆฌกๆ˜ ๅฐ„ๅคšไธชๆ•ฐๆฎ้›†๏ผˆ็คบไพ‹๏ผšRULER + math๏ผ‰๏ผš + +```bash +.venv/bin/python exp/exp5/map_exp2_cache_token_spans.py \ + --in_jsonl exp/exp2/data/niah_mq_q2.jsonl exp/exp2/data/math.jsonl \ + --out_dir exp/exp5/data \ + --old_tokenizer_model /opt/share/models/Qwen/Qwen3-8B \ + --new_tokenizer_model /opt/share/models/meta-llama/Llama-3.1-8B-Instruct +``` + +ๅฆ‚ๆžœ่พ“ๅ‡บๆ–‡ไปถๅทฒๅญ˜ๅœจ๏ผŒๅŠ  `--overwrite`ใ€‚ + +้ป˜่ฎค่กŒไธบ๏ผš่‹ฅๆŸๆกๆ ทๆœฌๆ— ๆณ•ๆ˜ ๅฐ„๏ผŒ่„šๆœฌไผšๅฐ†ๅ…ถ **drop** ๅนถๅœจ่พ“ๅ‡บ็ปŸ่ฎกไธญๆŠฅๅ‘Š๏ผ›ๅฆ‚้œ€ไธฅๆ ผไธ€่‡ดๆ€ง่ฏทๅŠ  `--strict`๏ผˆ้‡ๅˆฐ้ฆ–ไธชๅคฑ่ดฅๆ ทๆœฌ็›ดๆŽฅ้€€ๅ‡บ๏ผ‰ใ€‚ๅฆ‚ๆ€€็–‘ๅŽŸ็ผ“ๅญ˜ๅนถ้ž็”ฑ `--old_tokenizer_model` ไบง็”Ÿ๏ผŒๅฏๅŠ  `--allow_fallback_answer` ๅฏ็”จๅŸบไบŽ `metadata.boxed_answer` ็š„ๅ…œๅบ•ๅฎšไฝใ€‚ + +--- + +## Step 2๏ผš็”จ exp2 ็›ดๆŽฅ่ท‘ Llama ๅฝ’ๅ› ่ฏ„ๆต‹๏ผˆไฝ†ๆ•ฐๆฎ/่พ“ๅ‡บ้ƒฝๆŒ‡ๅ‘ exp5๏ผ‰ + +ๅ…ณ้”ฎ็‚น๏ผš +- **ๆ•ฐๆฎ่ฏปๅ–**๏ผš็”จ `--data_root exp/exp5/data`๏ผˆ่ฎฉ exp2 ่ฏปๅ–ๆ˜ ๅฐ„ๅŽ็š„็ผ“ๅญ˜๏ผ‰ +- **็ป“ๆžœ่พ“ๅ‡บ**๏ผš็”จ `--output_root exp/exp5/output`๏ผˆ้ฟๅ…ๅ†™ๅ…ฅ `exp/exp2/output`๏ผ‰ +- **ไธ่ฆๅŠ ** `--save_hop_traces`๏ผˆ้ฟๅ…ๅ†™ trace๏ผ‰ + +### RULER๏ผˆๅฏ่ท‘ recovery + faithfulness๏ผ‰ + +```bash +CUDA_VISIBLE_DEVICES=0 .venv/bin/python exp/exp2/run_exp.py \ + --datasets niah_mq_q2 \ + --data_root exp/exp5/data \ + --output_root exp/exp5/output \ + --attr_funcs ifr_all_positions,attnlrp,ifr_multi_hop_both \ + --model_path /opt/share/models/meta-llama/Llama-3.1-8B-Instruct \ + --cuda 0 \ + --num_examples 100 \ + --mode faithfulness_gen,recovery_ruler +``` + +### math๏ผˆๅช่ƒฝ่ท‘ faithfulness๏ผ›recovery ไผš่ขซ exp2 ๆ˜พๅผๆ‹’็ป๏ผ‰ + +```bash +CUDA_VISIBLE_DEVICES=0 .venv/bin/python exp/exp2/run_exp.py \ + --datasets math \ + --data_root exp/exp5/data \ + --output_root exp/exp5/output \ + --attr_funcs ifr_all_positions,attnlrp,ifr_multi_hop_both \ + --model_path /opt/share/models/meta-llama/Llama-3.1-8B-Instruct \ + --cuda 0 \ + --num_examples 100 \ + --mode faithfulness_gen +``` + +## ๅ…ณไบŽโ€œๆ˜ฏๅฆไผšๆฑกๆŸ“ exp2 ๆ–‡ไปถๅคนโ€ + +- **ไธไผšๆฑกๆŸ“ `exp/exp2/data/`**๏ผšๆˆ‘ไปฌไธๆ”น exp2 ็š„็ผ“ๅญ˜๏ผŒ่€Œๆ˜ฏ่พ“ๅ‡บๅˆฐ `exp/exp5/data/`ใ€‚ +- **ไธๅŠ  `--save_hop_traces` ไธไผšๅ†™ trace**ใ€‚ +- ไฝ†ๆณจๆ„๏ผš`exp/exp2/run_exp.py` ๆœฌ่บซ**ไธ€ๅฎšไผšๅ†™ CSV ๆŒ‡ๆ ‡ๆ–‡ไปถ**ๅˆฐ `--output_root`๏ผˆไปฃ็ ่กŒไธบๅฆ‚ๆญค๏ผŒexp5 ไธๆ”น exp2๏ผ‰๏ผŒๆ‰€ไปฅ่ฆๅšๅˆฐโ€œexp2 ๆ–‡ไปถๅคนไธๆ–ฐๅขžๆ–‡ไปถโ€๏ผŒ่ฏทๆŠŠ `--output_root` ๆŒ‡ๅ‘ `exp/exp5/output`๏ผˆๆˆ–ๅ…ถๅฎƒ็›ฎๅฝ•๏ผ‰ใ€‚ + +```bash +python exp/exp2/run_exp.py \ + --datasets niah_mq_q2 \ + --data_root exp/exp5/data \ + --output_root exp/exp5/output \ + --attr_funcs ifr_all_positions,attnlrp,ifr_multi_hop_both \ + --model_path /opt/share/models/meta-llama/Llama-3.1-8B-Instruct \ + --cuda 2,3,4,5,6,7 \ + --num_examples 100 \ + --mode faithfulness_gen \ + --n_hops 1 +&& python exp/exp2/run_exp.py \ + --datasets math \ + --data_root exp/exp5/data \ + --output_root exp/exp5/output \ + --attr_funcs ifr_all_positions,attnlrp,ifr_multi_hop_both \ + --model_path /opt/share/models/meta-llama/Llama-3.1-8B-Instruct \ + --cuda 2,3,4,5,6,7 \ + --num_examples 100 \ + --mode faithfulness_gen \ + --n_hops 1 +``` \ No newline at end of file diff --git a/exp/exp5/map_exp2_cache_token_spans.py b/exp/exp5/map_exp2_cache_token_spans.py new file mode 100644 index 0000000000000000000000000000000000000000..995a3b3aae818159d0f7d6e409943cea4c897e87 --- /dev/null +++ b/exp/exp5/map_exp2_cache_token_spans.py @@ -0,0 +1,407 @@ +#!/usr/bin/env python3 +"""Map exp2 cached JSONL token spans across tokenizers (Qwen -> Llama). + +Background +---------- +`exp/exp2/run_exp.py` expects cached datasets to provide token-level generation spans: + + - indices_to_explain: [start_tok, end_tok] (generation-token indices; closed interval) + - sink_span / thinking_span: same tokenizer convention as indices_to_explain + +These spans are computed under a specific tokenizer (often Qwen3-8B). When switching +to a different model/tokenizer (e.g., Llama-3.1-8B-Instruct), the stored spans can +become out-of-range and crash exp2 attribution (IndexError in token-span checks). + +This script remaps spans by: + 1) Tokenizing `target` with the OLD tokenizer to obtain offset_mapping + 2) Converting the OLD token span into a character span in `target` + 3) Tokenizing `target` with the NEW tokenizer and mapping the character span back + into NEW token indices + +Outputs are written under `exp/exp5/data/` by default, keeping `exp/exp2/` untouched. +""" + +from __future__ import annotations + +import argparse +import json +import sys +from pathlib import Path +from typing import Any, Dict, Iterable, List, Optional, Tuple + +from transformers import AutoTokenizer + + +REPO_ROOT = Path(__file__).resolve().parents[2] +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + + +def _split_args(values: Iterable[str]) -> List[str]: + out: List[str] = [] + for v in values: + for part in str(v).split(","): + part = part.strip() + if part: + out.append(part) + return out + + +def _load_tokenizer(tokenizer_model: str): + path = Path(tokenizer_model) + if path.exists(): + return AutoTokenizer.from_pretrained(path.as_posix(), local_files_only=True) + # May require network access; keep as fallback for environments that allow it. + return AutoTokenizer.from_pretrained(tokenizer_model) + + +def _is_token_span(span: Any) -> bool: + return ( + isinstance(span, list) + and len(span) == 2 + and all(isinstance(x, int) for x in span) + and span[0] >= 0 + and span[1] >= span[0] + ) + + +def _pick_old_span(obj: Dict[str, Any]) -> Optional[List[int]]: + span = obj.get("indices_to_explain") + if _is_token_span(span): + return list(span) + span = obj.get("sink_span") + if _is_token_span(span): + return list(span) + return None + + +def _offsets_to_char_span(offsets: Any, token_span: List[int]) -> Optional[Tuple[int, int]]: + """Convert a token span [start,end] to a character span [char_start,char_end) using offsets.""" + if offsets is None: + return None + if not isinstance(offsets, list): + return None + start_tok, end_tok = token_span + if end_tok >= len(offsets): + return None + + char_starts: List[int] = [] + char_ends: List[int] = [] + for idx in range(start_tok, end_tok + 1): + off = offsets[idx] + if off is None: + continue + if not (isinstance(off, (list, tuple)) and len(off) == 2): + continue + try: + s, e = int(off[0]), int(off[1]) + except Exception: + continue + if e <= s: + continue + char_starts.append(s) + char_ends.append(e) + + if not char_starts or not char_ends: + return None + return min(char_starts), max(char_ends) + + +def _char_span_to_token_span(offsets: Any, char_span: Tuple[int, int]) -> Optional[List[int]]: + """Convert a character span [char_start,char_end) to a token span [start,end] by overlap.""" + if offsets is None: + return None + if not isinstance(offsets, list): + return None + char_start, char_end = int(char_span[0]), int(char_span[1]) + if char_end <= char_start: + return None + + hit: List[int] = [] + for tok_idx, off in enumerate(offsets): + if off is None: + continue + if not (isinstance(off, (list, tuple)) and len(off) == 2): + continue + try: + s, e = int(off[0]), int(off[1]) + except Exception: + continue + if e <= s: + continue + if s < char_end and e > char_start: + hit.append(int(tok_idx)) + + if not hit: + return None + return [min(hit), max(hit)] + + +def _validate_span_with_eos(tokenizer, target: str, token_span: List[int]) -> bool: + eos = tokenizer.eos_token or "" + gen_ids = tokenizer(target + eos, add_special_tokens=False).input_ids + gen_len = int(len(gen_ids)) + return 0 <= token_span[0] <= token_span[1] < gen_len + + +def _guess_answer_text(obj: Dict[str, Any]) -> Optional[str]: + meta = obj.get("metadata") or {} + if isinstance(meta, dict): + boxed = (meta.get("boxed_answer") or "").strip() + if boxed: + return boxed + ref = (meta.get("reference_answer") or "").strip() + if ref: + return ref + tgt = obj.get("target") + if isinstance(tgt, str) and tgt.strip(): + # Common exp2 cache convention: last line is the final answer. + last_line = tgt.strip().splitlines()[-1].strip() + return last_line or None + return None + + +def _fallback_map_via_answer_text( + obj: Dict[str, Any], + *, + new_tokenizer, +) -> Optional[List[int]]: + tgt = obj.get("target") + if not isinstance(tgt, str) or not tgt: + return None + + from exp.exp2.dataset_utils import CachedExample, attach_spans_from_answer # lazy import + + answer_text = _guess_answer_text(obj) + ex = CachedExample( + prompt=str(obj.get("prompt") or ""), + target=tgt, + indices_to_explain=None, + attr_mask_indices=obj.get("attr_mask_indices"), + sink_span=None, + thinking_span=None, + metadata=obj.get("metadata") or {}, + ) + out = attach_spans_from_answer(ex, new_tokenizer, answer_text) + if out.sink_span is None: + return None + if not _is_token_span(out.sink_span): + return None + return list(out.sink_span) + + +def _map_one_obj( + obj: Dict[str, Any], + *, + old_tokenizer, + new_tokenizer, + allow_fallback_answer: bool, +) -> Tuple[Optional[Dict[str, Any]], Optional[str]]: + target = obj.get("target") + if not isinstance(target, str) or not target: + return None, "missing_target" + + old_span = _pick_old_span(obj) + if old_span is None: + return None, "missing_old_span" + + # 1) Old token span -> char span in target. + old_enc = old_tokenizer(target, add_special_tokens=False, return_offsets_mapping=True) + old_offsets = old_enc.get("offset_mapping") + char_span = _offsets_to_char_span(old_offsets, old_span) + if char_span is None: + if not allow_fallback_answer: + return None, "old_span_to_char_failed" + new_span = _fallback_map_via_answer_text(obj, new_tokenizer=new_tokenizer) + if new_span is None: + return None, "fallback_answer_failed" + if not _validate_span_with_eos(new_tokenizer, target, new_span): + return None, "fallback_answer_span_invalid" + mapped = dict(obj) + mapped["indices_to_explain"] = new_span + mapped["sink_span"] = new_span + mapped["thinking_span"] = [0, new_span[0] - 1] if new_span[0] > 0 else None + meta = mapped.get("metadata") + if not isinstance(meta, dict): + meta = {} + meta = dict(meta) + meta["exp5_span_map_method"] = "answer_text" + mapped["metadata"] = meta + return mapped, None + + # 2) Char span -> new token span. + new_enc = new_tokenizer(target, add_special_tokens=False, return_offsets_mapping=True) + new_offsets = new_enc.get("offset_mapping") + new_span = _char_span_to_token_span(new_offsets, char_span) + if new_span is None: + if not allow_fallback_answer: + return None, "char_to_new_span_failed" + new_span = _fallback_map_via_answer_text(obj, new_tokenizer=new_tokenizer) + if new_span is None: + return None, "fallback_answer_failed" + + if not _validate_span_with_eos(new_tokenizer, target, new_span): + if not allow_fallback_answer: + return None, "new_span_invalid" + fb = _fallback_map_via_answer_text(obj, new_tokenizer=new_tokenizer) + if fb is None or not _validate_span_with_eos(new_tokenizer, target, fb): + return None, "fallback_answer_span_invalid" + new_span = fb + + mapped = dict(obj) + mapped["indices_to_explain"] = new_span + mapped["sink_span"] = new_span + mapped["thinking_span"] = [0, new_span[0] - 1] if new_span[0] > 0 else None + + meta = mapped.get("metadata") + if not isinstance(meta, dict): + meta = {} + meta = dict(meta) + meta["exp5_span_map_method"] = "token_span_char_align" + mapped["metadata"] = meta + return mapped, None + + +def _read_jsonl(path: Path) -> Iterable[Dict[str, Any]]: + with path.open("r", encoding="utf-8") as f: + for line_no, line in enumerate(f, start=1): + if not line.strip(): + continue + try: + obj = json.loads(line) + except json.JSONDecodeError as exc: # pragma: no cover + raise RuntimeError(f"Invalid JSON at {path}:{line_no}: {exc}") from exc + if not isinstance(obj, dict): + raise RuntimeError(f"Expected JSON object per line at {path}:{line_no}.") + yield obj + + +def _write_jsonl(path: Path, rows: Iterable[Dict[str, Any]]) -> int: + path.parent.mkdir(parents=True, exist_ok=True) + count = 0 + with path.open("w", encoding="utf-8") as f: + for obj in rows: + f.write(json.dumps(obj, ensure_ascii=False) + "\n") + count += 1 + return count + + +def _default_old_tokenizer() -> str: + # Repo defaults used in exp2 README examples for span extraction. + return "/opt/share/models/Qwen/Qwen3-8B" + + +def _default_new_tokenizer() -> str: + return "/opt/share/models/meta-llama/Llama-3.1-8B-Instruct" + + +def main() -> None: + ap = argparse.ArgumentParser("Map exp2 cache token spans from an old tokenizer to a new tokenizer.") + ap.add_argument( + "--in_jsonl", + type=str, + nargs="+", + required=True, + help="One or more exp2 cached JSONL files (comma-separated also accepted).", + ) + ap.add_argument( + "--out_dir", + type=str, + default="exp/exp5/data", + help="Output directory for mapped JSONL files.", + ) + ap.add_argument( + "--old_tokenizer_model", + type=str, + default=_default_old_tokenizer(), + help="Tokenizer used to produce the original token spans (default: Qwen3-8B local path).", + ) + ap.add_argument( + "--new_tokenizer_model", + type=str, + default=_default_new_tokenizer(), + help="Tokenizer to map spans into (default: Llama-3.1-8B-Instruct local path).", + ) + ap.add_argument("--strict", action="store_true", help="Fail on the first example that cannot be mapped.") + ap.add_argument( + "--allow_fallback_answer", + action="store_true", + help=( + "If span alignment fails, try to recompute spans by locating metadata.boxed_answer in target " + "(useful when caches were not built with the assumed old tokenizer)." + ), + ) + ap.add_argument( + "--overwrite", + action="store_true", + help="Overwrite output files if they already exist.", + ) + args = ap.parse_args() + + in_paths = [Path(p) for p in _split_args(args.in_jsonl)] + out_dir = Path(args.out_dir) + + old_tok = _load_tokenizer(str(args.old_tokenizer_model)) + new_tok = _load_tokenizer(str(args.new_tokenizer_model)) + + # exp2 convention: ensure a pad token exists for downstream perturbation. + if new_tok.pad_token is None and new_tok.eos_token is not None: + new_tok.pad_token = new_tok.eos_token + + summary: Dict[str, Any] = { + "old_tokenizer_model": str(args.old_tokenizer_model), + "new_tokenizer_model": str(args.new_tokenizer_model), + "datasets": [], + } + + for in_path in in_paths: + if not in_path.exists(): + raise SystemExit(f"Missing input JSONL: {in_path}") + out_path = out_dir / in_path.name + if out_path.exists() and not bool(args.overwrite): + raise SystemExit(f"Refusing to overwrite existing output: {out_path} (use --overwrite)") + + total = 0 + mapped_ok = 0 + dropped = 0 + errors: Dict[str, int] = {} + + mapped_rows: List[Dict[str, Any]] = [] + for obj in _read_jsonl(in_path): + total += 1 + mapped, err = _map_one_obj( + obj, + old_tokenizer=old_tok, + new_tokenizer=new_tok, + allow_fallback_answer=bool(args.allow_fallback_answer), + ) + if err is not None or mapped is None: + errors[err or "unknown_error"] = errors.get(err or "unknown_error", 0) + 1 + if bool(args.strict): + raise SystemExit(f"Failed to map {in_path} example #{total}: {err}") + dropped += 1 + continue + mapped_ok += 1 + mapped_rows.append(mapped) + + written = _write_jsonl(out_path, mapped_rows) + if written != mapped_ok: # pragma: no cover + raise SystemExit(f"Internal error: written={written} != mapped_ok={mapped_ok}") + + record = { + "in_jsonl": str(in_path), + "out_jsonl": str(out_path), + "total": int(total), + "mapped_ok": int(mapped_ok), + "dropped": int(dropped), + "errors": errors, + } + summary["datasets"].append(record) + print(json.dumps(record, ensure_ascii=False)) + + # Human-readable compact summary at end. + print(json.dumps(summary, ensure_ascii=False, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/exp/proc/README.md b/exp/proc/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a657df27786334a48080c9af86655895db6e6b1f --- /dev/null +++ b/exp/proc/README.md @@ -0,0 +1,98 @@ +# exp/proc๏ผˆexp2 trace ๆ˜ ๅฐ„/ๅฏนๅค–ๅฏผๅ‡บ๏ผ‰ + +ๆœฌ็›ฎๅฝ•ๆไพ›ๆŠŠ `exp/exp2/run_exp.py --save_hop_traces` ไบงๅ‡บ็š„ trace ็ป“ๆžœ๏ผŒๆ•ด็†ๆˆโ€œ็ป™ๅˆไฝœ่€…ไฝฟ็”จโ€็š„็ฒพ็ฎ€ๆ ทๆœฌ็บง `.npz` ็š„ๅทฅๅ…ทใ€‚ + +ไธป่ฆๆ–‡ไปถ๏ผš +- `exp/proc/map_exp2_traces_to_proc.py`๏ผš่ฏปๅ– exp2 ็š„ trace run ๆ–‡ไปถๅคน๏ผˆ`manifest.jsonl` + `ex_*.npz`๏ผ‰๏ผŒ่พ“ๅ‡บ็ฒพ็ฎ€ๆ ผๅผๅˆฐ `exp/proc/output/`ใ€‚ + +--- + +## ่พ“ๅ…ฅ่ฆๆฑ‚ + +ไฝ ้œ€่ฆๆไพ›๏ผˆๆˆ–ๅฏ่‡ชๅŠจๆŽจๆ–ญ๏ผ‰๏ผš +- `--trace_dir`๏ผšexp2 ็š„ trace run ๆ–‡ไปถๅคน๏ผŒไพ‹ๅฆ‚๏ผš + - `exp/exp2/output/traces/exp/exp2/data/morehopqa.jsonl/qwen-8B/ifr_all_positions_mfaithfulness_gen_95ex/` +- `--dataset_jsonl`๏ผšไธŽ่ฏฅ trace run ๅฏนๅบ”็š„ exp2 ็ผ“ๅญ˜ๆ•ฐๆฎ้›†๏ผˆๅฟ…้กปๅŒ…ๅซ `prompt` + `target`๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš + - `exp/exp2/data/morehopqa.jsonl` +- `--tokenizer_model`๏ผšไธŽ exp2 ๅฝ’ๅ› ๆ—ถไธ€่‡ด็š„ tokenizer๏ผˆๆœฌๅœฐ่ทฏๅพ„ๆˆ–ๆจกๅž‹ๅ๏ผ‰๏ผŒไพ‹ๅฆ‚๏ผš + - `/opt/share/models/Qwen/Qwen3-8B/` + +ๆณจๆ„๏ผš +- ๆœฌ่„šๆœฌไผšไธฅๆ ผๅคๅˆป exp2 ็š„ token ๅฏน้ฝ้€ป่พ‘๏ผˆprompt ๅ‰ๅฏผ็ฉบๆ ผใ€generation ็”จ `target + eos_token` ๅ† decode + offset ๅˆ‡็‰‡๏ผ‰๏ผŒๅ› ๆญค tokenizer ๅฟ…้กปไธŽ exp2 ๅฝ’ๅ› ไธ€่‡ด๏ผŒๅฆๅˆ™ไผš็›ดๆŽฅๆŠฅ้”™๏ผˆ้•ฟๅบฆๅฏนไธไธŠ๏ผ‰ใ€‚ +- ๆ ทๆœฌๅŒน้…ไฝฟ็”จ `manifest.jsonl` ไธญ็š„ `prompt_sha1/target_sha1` ๅฏน้ฝ `--dataset_jsonl`๏ผ›ๆ‰€ไปฅ `--dataset_jsonl` ๅฟ…้กปๆ˜ฏๅฝ“ๆฌก trace run ไฝฟ็”จ็š„้‚ฃไปฝ็ผ“ๅญ˜ใ€‚ + +--- + +## ่พ“ๅ‡บไฝ็ฝฎไธŽๅ‘ฝๅ + +้ป˜่ฎค่พ“ๅ‡บๅˆฐ๏ผš +- `exp/proc/output//` + +ไพ‹ๅฆ‚่พ“ๅ…ฅ๏ผš +- `.../output/traces/exp/exp2/data/morehopqa.jsonl/qwen-8B//` + +้ป˜่ฎค่พ“ๅ‡บ๏ผš +- `exp/proc/output/exp/exp2/data/morehopqa.jsonl/qwen-8B//` + +ไฝ ไนŸๅฏไปฅ็”จ `--out_dir` ๆ˜พๅผๆŒ‡ๅฎš่พ“ๅ‡บ็›ฎๅฝ•ใ€‚ + +่พ“ๅ‡บ็›ฎๅฝ•ๅ†…ๆฏไธชๆ ทๆœฌไธ€ไธชๆ–‡ไปถ๏ผš`ex_000000.npz`ใ€`ex_000001.npz` โ€ฆ + +--- + +## ่พ“ๅ‡บ `.npz` ๅญ—ๆฎต๏ผˆ็ฒพ็ฎ€ไธ”ไป…ๅŒ…ๅซๅฟ…่ฆไฟกๆฏ๏ผ‰ + +ๆฏไธช่พ“ๅ‡บๆ ทๆœฌ `.npz` **ไป…ๅŒ…ๅซ**ไธ‹ๅˆ—้”ฎ๏ผš +- `attr`๏ผš`float32[L]`๏ผŒrow ๅฝ’ๅ› ๅ‘้‡๏ผ›ๅทฒๅŽปๆމ chat template๏ผŒไธ”ๅŽปๆމ EOS๏ผŒไป…่ฆ†็›– `input+cot+output` ็š„ๆœ‰ๆ•ˆ tokenใ€‚ +- `hop`๏ผš`float32[H, L]`๏ผˆๅฏ้€‰๏ผŒไป… FT-IFR ็ฑปๆ–นๆณ•๏ผ‰๏ผŒ้€ hop ็š„ๅ‘้‡๏ผ›ๅŒๆ ทๅทฒๅŽปๆމ EOS๏ผŒๅนถไธŽ `attr` ็ญ‰้•ฟๅฏน้ฝใ€‚ +- `tok`๏ผš`U[L]`๏ผŒไธŽ `attr/hop` ไธฅๆ ผๅฏน้ฝ็š„ token ๆ–‡ๆœฌ็‰‡ๆฎตๅบๅˆ—๏ผˆๅŒๆ ทไธๅซ chat template ไธŽ EOS๏ผ‰ใ€‚ +- `span_in`๏ผš`int64[2]`๏ผŒinput ๅœจๅ‘้‡ไธญ็š„้—ญๅŒบ้—ด่Œƒๅ›ดใ€‚ +- `span_cot`๏ผš`int64[2]`๏ผŒcot ๅœจๅ‘้‡ไธญ็š„้—ญๅŒบ้—ด่Œƒๅ›ด๏ผˆๆ—  cot ๆ—ถไธบ `[-1, -1]`๏ผ‰ใ€‚ +- `span_out`๏ผš`int64[2]`๏ผŒoutput ๅœจๅ‘้‡ไธญ็š„้—ญๅŒบ้—ด่Œƒๅ›ดใ€‚ +- `rise`๏ผš`float64`๏ผŒrow ็š„ RISE๏ผˆfaithfulness๏ผ‰ใ€‚ +- `mas`๏ผš`float64`๏ผŒrow ็š„ MAS๏ผˆfaithfulness๏ผ‰ใ€‚ +- `recovery`๏ผš`float64`๏ผŒrow ็š„ Recovery@10%๏ผˆๆฒกๆœ‰ recovery ๆ—ถไธบ NaN๏ผ‰ใ€‚ + +--- + +## ็”จๆณ•็คบไพ‹ + +ๆœ€ๅธธ็”จ๏ผˆๅปบ่ฎฎๆ˜พๅผไผ ๅ…ฅ dataset ไธŽ tokenizer๏ผ‰๏ผš +```bash +python exp/proc/map_exp2_traces_to_proc.py \ + --trace_dir exp/exp2/output/traces/exp/exp2/data/morehopqa.jsonl/qwen-8B/ifr_all_positions_mfaithfulness_gen_95ex \ + --dataset_jsonl exp/exp2/data/morehopqa.jsonl \ + --tokenizer_model /opt/share/models/Qwen/Qwen3-8B/ +``` + +ๆ˜พๅผๆŒ‡ๅฎš่พ“ๅ‡บ็›ฎๅฝ•๏ผˆ้ฟๅ…้ป˜่ฎคๅŒๆž„่ทฏๅพ„๏ผ‰๏ผš +```bash +python exp/proc/map_exp2_traces_to_proc.py \ + --trace_dir exp/exp2/output/traces/exp/exp2/data/math.jsonl/qwen-8B/ifr_multi_hop_both_n1_mfaithfulness_gen_100ex/ \ + --dataset_jsonl exp/exp2/data/math.jsonl \ + --tokenizer_model /opt/share/models/Qwen/Qwen3-8B/ \ + --out_dir exp/proc/output/math_ifr_multi_hop_both +``` + +่ฐƒ่ฏ•๏ผšๅชๅค„็†ๅ‰ 5 ๆกใ€ๅ…่ฎธ่ฆ†็›–่พ“ๅ‡บๆ–‡ไปถ๏ผš +```bash +python exp/proc/map_exp2_traces_to_proc.py \ + --trace_dir ... \ + --dataset_jsonl ... \ + --tokenizer_model ... \ + --limit 5 \ + --overwrite +``` + +--- + +## ๅธธ่ง้—ฎ้ข˜ + +- ๆŠฅ้”™ โ€œPrompt/Generation token length mismatchโ€ + - ๅ‡ ไนŽๆ€ปๆ˜ฏ tokenizer ไธไธ€่‡ด๏ผ›่ฏท็กฎ่ฎค `--tokenizer_model` ไธŽ exp2 ๅฝ’ๅ› ๆ—ถไฝฟ็”จ็š„ tokenizer ๅฎŒๅ…จไธ€่‡ด๏ผˆๅปบ่ฎฎ็›ดๆŽฅ็”จๅŒไธ€ไธช `--model_path`๏ผ‰ใ€‚ +- ๆŠฅ้”™ โ€œFailed to match manifest sha1 to dataset_jsonlโ€ + - `--dataset_jsonl` ไธๆ˜ฏๅฝ“ๆฌก trace run ไฝฟ็”จ็š„็ผ“ๅญ˜๏ผŒๆˆ–็ผ“ๅญ˜้‡Œๆฒกๆœ‰ `target`ใ€‚ +- FT-IFR ๆ–นๆณ•่พ“ๅ‡บ็ผบ `hop` + - ๅฏน `ifr_multi_hop_stop_words/ifr_multi_hop_both/ifr_multi_hop_split_hop/ifr_in_all_gen`๏ผŒexp2 trace ๅฟ…้กปๅŒ…ๅซ `vh`๏ผ›่‹ฅ trace ่พƒๆ—ง่ฏท้‡ๆ–ฐ่ท‘ exp2๏ผˆๅธฆ `--save_hop_traces`๏ผ‰ใ€‚ + - ๅฆ‚็กฎๆœ‰้œ€่ฆๅฏๅŠ  `--allow_missing_ft_hops` ๅผบ่กŒ่พ“ๅ‡บ๏ผˆไธๆŽจ่๏ผ‰ใ€‚ + diff --git a/exp/proc/map_exp2_traces_to_proc.py b/exp/proc/map_exp2_traces_to_proc.py new file mode 100644 index 0000000000000000000000000000000000000000..17cc7a5b726971a8e40a21cd3ff2eb6bec784ded --- /dev/null +++ b/exp/proc/map_exp2_traces_to_proc.py @@ -0,0 +1,411 @@ +#!/usr/bin/env python3 +"""Map exp2 trace artifacts into a collaborator-friendly per-sample NPZ format. + +Input: an exp2 trace run directory produced by `exp/exp2/run_exp.py --save_hop_traces`, +e.g.: + + exp/exp2/output/traces/exp/exp2/data/morehopqa.jsonl/qwen-8B/ifr_all_positions_mfaithfulness_gen_95ex/ + +This directory contains: + - manifest.jsonl (one JSON object per sample) + - ex_*.npz (per-sample vectors and scores) + +Output: per-sample NPZ files under `exp/proc/output/` (or a user-provided output path), +each containing only: + - attr: row attribution vector over [input + CoT + output] tokens, with chat template and EOS removed + - hop: per-hop vectors (FT-IFR only), aligned to attr (optional) + - tok: tokenized text pieces aligned to attr/hop (no chat template, no EOS) + - span_in/span_cot/span_out: inclusive ranges for input/CoT/output in the above vectors + - rise/mas: row faithfulness scores (RISE, MAS) + - recovery: row Recovery@10% score (NaN when unavailable) + +This script is intentionally self-contained under exp/proc/ and does not modify exp2. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from dataclasses import dataclass +from pathlib import Path +from typing import Dict, List, Optional, Tuple + +import numpy as np +from transformers import AutoTokenizer + + +FT_IFR_ATTR_FUNCS: set[str] = { + "ifr_in_all_gen", + "ifr_multi_hop_stop_words", + "ifr_multi_hop_both", + "ifr_multi_hop_split_hop", +} + + +def _sha1_text(text: str) -> str: + return hashlib.sha1(text.encode("utf-8")).hexdigest() + + +def _load_tokenizer(tokenizer_model: str): + tok_path = Path(tokenizer_model) + if tok_path.exists(): + tokenizer = AutoTokenizer.from_pretrained(tok_path.as_posix(), local_files_only=True) + else: + tokenizer = AutoTokenizer.from_pretrained(tokenizer_model) + if tokenizer.eos_token is None: + raise SystemExit("Tokenizer is missing eos_token; cannot match exp2 generation tokenization.") + if tokenizer.pad_token is None and tokenizer.eos_token is not None: + tokenizer.pad_token = tokenizer.eos_token + return tokenizer + + +def _decode_text_into_tokens(tokenizer, text: str) -> List[str]: + """Mirror llm_attr.LLMAttribution.decode_text_into_tokens (offset-slice tokens).""" + enc = tokenizer(text, return_offsets_mapping=True, add_special_tokens=False) + ids = enc.get("input_ids") + offsets = enc.get("offset_mapping") + if ids is None or offsets is None: + raise ValueError("Tokenizer must provide input_ids and offset_mapping for exact exp2 token alignment.") + if len(ids) != len(offsets): + raise ValueError("Tokenizer returned mismatched input_ids vs offset_mapping lengths.") + tokens: List[str] = [] + for start, end in offsets: + tokens.append(text[int(start) : int(end)]) + return tokens + + +@dataclass(frozen=True) +class DatasetEntry: + prompt: str + target: str + + +def _index_dataset_by_sha1(dataset_jsonl: Path) -> Dict[Tuple[str, str], DatasetEntry]: + """Build (prompt_sha1, target_sha1) -> (prompt, target) for cache lookup.""" + index: Dict[Tuple[str, str], DatasetEntry] = {} + collisions: Dict[Tuple[str, str], int] = {} + + with dataset_jsonl.open("r", encoding="utf-8") as f: + for line_num, line in enumerate(f, start=1): + if not line.strip(): + continue + obj = json.loads(line) + prompt = str(obj.get("prompt") or "") + target = obj.get("target") + if target is None: + # exp2 trace matching requires cached targets. + continue + target = str(target) + + key = (_sha1_text(prompt), _sha1_text(target)) + if key in index: + collisions[key] = collisions.get(key, 1) + 1 + continue + index[key] = DatasetEntry(prompt=prompt, target=target) + + if collisions: + raise SystemExit( + "Dataset cache contains duplicate (prompt,target) pairs; cannot uniquely match by sha1. " + f"Example collision count={next(iter(collisions.values()))}. " + f"dataset_jsonl={dataset_jsonl}" + ) + + if not index: + raise SystemExit( + "No usable (prompt,target) pairs found in dataset cache. " + "Ensure you pass the exp2 cached JSONL used for attribution (with target filled)." + ) + + return index + + +def _infer_trace_suffix(trace_dir: Path) -> Optional[Path]: + parts = list(trace_dir.parts) + if "traces" not in parts: + return None + idx = parts.index("traces") + suffix_parts = parts[idx + 1 :] + if not suffix_parts: + return None + return Path(*suffix_parts) + + +def _parse_manifest(manifest_path: Path) -> List[dict]: + records: List[dict] = [] + with manifest_path.open("r", encoding="utf-8") as f: + for line in f: + if not line.strip(): + continue + records.append(json.loads(line)) + if not records: + raise SystemExit(f"Empty manifest.jsonl: {manifest_path}") + return records + + +def _read_span(npz: np.lib.npyio.NpzFile, key: str) -> Optional[Tuple[int, int]]: + if key not in npz.files: + return None + arr = npz[key] + if arr.shape != (2,): + raise ValueError(f"Expected {key} to have shape (2,), got {arr.shape}.") + return int(arr[0]), int(arr[1]) + + +def _span_or_empty(span: Optional[Tuple[int, int]]) -> Tuple[int, int]: + if span is None: + return -1, -1 + return int(span[0]), int(span[1]) + + +def _tokenize_for_exp2_alignment( + tokenizer, + *, + prompt: str, + target: str, + expected_prompt_len: int, + expected_gen_len: int, +) -> List[str]: + prompt_text = " " + (prompt or "") + prompt_tokens = _decode_text_into_tokens(tokenizer, prompt_text) + if len(prompt_tokens) != int(expected_prompt_len): + raise ValueError(f"Prompt token length mismatch: expected {expected_prompt_len}, got {len(prompt_tokens)}.") + + gen_ids = tokenizer(target + tokenizer.eos_token, add_special_tokens=False).input_ids + gen_text = tokenizer.decode(gen_ids, skip_special_tokens=False, clean_up_tokenization_spaces=False) + gen_tokens = _decode_text_into_tokens(tokenizer, gen_text) + if len(gen_tokens) != int(expected_gen_len): + raise ValueError(f"Generation token length mismatch: expected {expected_gen_len}, got {len(gen_tokens)}.") + + gen_tokens_no_eos = gen_tokens[:-1] if gen_tokens else [] + return prompt_tokens + gen_tokens_no_eos + + +def _clamp_span(span: Optional[Tuple[int, int]], *, max_index: int) -> Optional[Tuple[int, int]]: + if span is None: + return None + start, end = int(span[0]), int(span[1]) + if max_index < 0: + return None + if end < 0 or start > max_index: + return None + start = max(0, start) + end = min(max_index, end) + if end < start: + return None + return start, end + + +def _proc_one( + *, + trace_npz_path: Path, + record: dict, + dataset_index: Dict[Tuple[str, str], DatasetEntry], + tokenizer, + out_path: Path, + overwrite: bool, + allow_missing_ft_hops: bool, +) -> None: + prompt_sha1 = str(record.get("prompt_sha1") or "") + target_sha1 = str(record.get("target_sha1") or "") + if not prompt_sha1 or not target_sha1: + raise ValueError("manifest record missing prompt_sha1/target_sha1; cannot match dataset.") + + entry = dataset_index.get((prompt_sha1, target_sha1)) + if entry is None: + raise ValueError( + "Failed to match manifest sha1 to dataset_jsonl. " + "Ensure --dataset_jsonl points to the exact cached JSONL used for this trace run." + ) + + if out_path.exists() and not overwrite: + raise FileExistsError(f"Refusing to overwrite existing file: {out_path} (use --overwrite).") + out_path.parent.mkdir(parents=True, exist_ok=True) + + with np.load(trace_npz_path, allow_pickle=False) as f: + prompt_len = int(np.asarray(f.get("prompt_len")).item()) + gen_len = int(np.asarray(f.get("gen_len")).item()) + total_len = prompt_len + gen_len + gen_no_eos = max(0, gen_len - 1) + L = prompt_len + gen_no_eos + + v_row_all = f.get("v_row_all") + if v_row_all is None: + raise ValueError("Missing v_row_all in trace npz; cannot build row attribution vector.") + v_row_all = np.asarray(v_row_all, dtype=np.float32) + if v_row_all.ndim != 1 or int(v_row_all.shape[0]) != int(total_len): + raise ValueError(f"v_row_all shape mismatch: expected ({total_len},), got {tuple(v_row_all.shape)}.") + attr = v_row_all[:L] + + indices_to_explain = _read_span(f, "indices_to_explain_gen") + sink_span_gen = _read_span(f, "sink_span_gen") or indices_to_explain + if sink_span_gen is None: + raise ValueError("Missing sink_span_gen/indices_to_explain_gen; cannot define output span.") + thinking_span_gen = _read_span(f, "thinking_span_gen") + if thinking_span_gen is None: + sink_start = int(sink_span_gen[0]) + think_end = sink_start - 1 + thinking_span_gen = (0, think_end) if think_end >= 0 else None + + sink_span_gen = _clamp_span(sink_span_gen, max_index=gen_no_eos - 1) + thinking_span_gen = _clamp_span(thinking_span_gen, max_index=gen_no_eos - 1) + + span_in = (0, prompt_len - 1) if prompt_len > 0 else (-1, -1) + span_cot = ( + (prompt_len + thinking_span_gen[0], prompt_len + thinking_span_gen[1]) + if thinking_span_gen is not None + else (-1, -1) + ) + span_out = ( + (prompt_len + sink_span_gen[0], prompt_len + sink_span_gen[1]) if sink_span_gen is not None else (-1, -1) + ) + + tokens = _tokenize_for_exp2_alignment( + tokenizer, + prompt=entry.prompt, + target=entry.target, + expected_prompt_len=prompt_len, + expected_gen_len=gen_len, + ) + if len(tokens) != int(L): + raise ValueError(f"Token length mismatch after EOS drop: expected {L}, got {len(tokens)}.") + + # Scores: row = index 1. + rise = float("nan") + mas = float("nan") + faith = f.get("faithfulness_scores") + if faith is not None: + faith = np.asarray(faith, dtype=np.float64) + if faith.shape != (3, 3): + raise ValueError(f"faithfulness_scores shape mismatch: expected (3,3), got {tuple(faith.shape)}.") + rise = float(faith[1, 0]) + mas = float(faith[1, 1]) + + recovery = float("nan") + rec = f.get("recovery_scores") + if rec is not None: + rec = np.asarray(rec, dtype=np.float64) + if rec.shape != (3,): + raise ValueError(f"recovery_scores shape mismatch: expected (3,), got {tuple(rec.shape)}.") + recovery = float(rec[1]) + + out_payload = { + "attr": np.asarray(attr, dtype=np.float32), + "tok": np.asarray(tokens, dtype=np.str_), + "span_in": np.asarray(span_in, dtype=np.int64), + "span_cot": np.asarray(span_cot, dtype=np.int64), + "span_out": np.asarray(span_out, dtype=np.int64), + "rise": np.asarray(rise, dtype=np.float64), + "mas": np.asarray(mas, dtype=np.float64), + "recovery": np.asarray(recovery, dtype=np.float64), + } + + attr_func = str(record.get("attr_func") or "") + want_hops = attr_func in FT_IFR_ATTR_FUNCS + if want_hops: + vh = f.get("vh") + if vh is None: + if not allow_missing_ft_hops: + raise ValueError( + f"FT-IFR method '{attr_func}' requires per-hop vectors but trace npz is missing 'vh'. " + "Re-run exp2 with --save_hop_traces using the updated code." + ) + else: + vh = np.asarray(vh, dtype=np.float32) + if vh.ndim != 2 or int(vh.shape[1]) != int(total_len): + raise ValueError( + f"vh shape mismatch: expected (H,{total_len}), got {tuple(vh.shape)} for {trace_npz_path}." + ) + out_payload["hop"] = vh[:, :L] + + np.savez_compressed(out_path, **out_payload) + + +def main() -> None: + ap = argparse.ArgumentParser("Map exp2 trace folder -> exp/proc/output per-sample npz files.") + ap.add_argument("--trace_dir", type=str, required=True, help="Path to an exp2 trace run directory (contains manifest.jsonl).") + ap.add_argument("--dataset_jsonl", type=str, default=None, help="Path to the exp2 cached dataset JSONL used for this trace.") + ap.add_argument( + "--tokenizer_model", + type=str, + required=True, + help="Tokenizer model name or local path (must match exp2 attribution tokenizer).", + ) + ap.add_argument("--out_root", type=str, default="exp/proc/output", help="Root directory for proc outputs.") + ap.add_argument("--out_dir", type=str, default=None, help="Optional explicit output directory (overrides --out_root).") + ap.add_argument("--overwrite", action="store_true", help="Overwrite existing output files if present.") + ap.add_argument("--limit", type=int, default=None, help="Optional limit on number of samples to process (debug).") + ap.add_argument( + "--allow_missing_ft_hops", + action="store_true", + help="Allow producing FT-IFR outputs even when per-hop vectors (vh) are missing (not recommended).", + ) + args = ap.parse_args() + + trace_dir = Path(args.trace_dir) + if not trace_dir.exists() or not trace_dir.is_dir(): + raise SystemExit(f"Missing trace_dir: {trace_dir}") + manifest_path = trace_dir / "manifest.jsonl" + if not manifest_path.exists(): + raise SystemExit(f"Missing manifest.jsonl: {manifest_path}") + + dataset_jsonl: Optional[Path] = Path(args.dataset_jsonl) if args.dataset_jsonl else None + if dataset_jsonl is None: + suffix = _infer_trace_suffix(trace_dir) + if suffix is not None and len(suffix.parts) >= 3: + # suffix = // + inferred_dataset = Path(*suffix.parts[:-2]) + if inferred_dataset.exists() and inferred_dataset.is_file(): + dataset_jsonl = inferred_dataset + if dataset_jsonl is None: + raise SystemExit("Please pass --dataset_jsonl (could not infer it from --trace_dir).") + if not dataset_jsonl.exists(): + raise SystemExit(f"Missing --dataset_jsonl: {dataset_jsonl}") + + tokenizer = _load_tokenizer(str(args.tokenizer_model)) + dataset_index = _index_dataset_by_sha1(dataset_jsonl) + records = _parse_manifest(manifest_path) + + if args.out_dir: + out_dir = Path(args.out_dir) + else: + suffix = _infer_trace_suffix(trace_dir) + out_dir = Path(args.out_root) / suffix if suffix is not None else Path(args.out_root) / trace_dir.name + out_dir.mkdir(parents=True, exist_ok=True) + + total = len(records) + limit = args.limit + if limit is not None: + if limit <= 0: + raise SystemExit("--limit must be a positive integer.") + total = min(total, int(limit)) + + processed = 0 + for record in records[:total]: + file_name = str(record.get("file") or "") + if not file_name: + raise SystemExit("manifest record missing 'file' field.") + trace_npz_path = trace_dir / file_name + if not trace_npz_path.exists(): + raise SystemExit(f"Missing trace npz referenced by manifest: {trace_npz_path}") + + out_path = out_dir / file_name + try: + _proc_one( + trace_npz_path=trace_npz_path, + record=record, + dataset_index=dataset_index, + tokenizer=tokenizer, + out_path=out_path, + overwrite=bool(args.overwrite), + allow_missing_ft_hops=bool(args.allow_missing_ft_hops), + ) + except Exception as exc: + raise SystemExit(f"Failed processing {trace_npz_path}: {exc}") from exc + processed += 1 + + print(f"Wrote {processed} proc samples -> {out_dir}") + + +if __name__ == "__main__": + main() diff --git a/exp/proc_1/README.md b/exp/proc_1/README.md new file mode 100644 index 0000000000000000000000000000000000000000..365214657b1aaeacae01721f67057fcffe277479 --- /dev/null +++ b/exp/proc_1/README.md @@ -0,0 +1,72 @@ +# exp/proc_1๏ผˆexp2 trace ๆ˜ ๅฐ„/ๅฏนๅค–ๅฏผๅ‡บ v1๏ผ‰ + +ๆœฌ็›ฎๅฝ•ๆไพ›ๆŠŠ `exp/exp2/run_exp.py --save_hop_traces` ไบงๅ‡บ็š„ trace ็ป“ๆžœ๏ผŒๆ•ด็†ๆˆโ€œ็ป™ๅˆไฝœ่€…ไฝฟ็”จโ€็š„็ฒพ็ฎ€ๆ ทๆœฌ็บง `.npz` ็š„ๅทฅๅ…ท๏ผˆv1๏ผ‰ใ€‚ + +ไธŽ `exp/proc/` ็š„ๅŒบๅˆซ๏ผš +- ๅŽปๆމ `tok`๏ผˆ้€ token ๆ–‡ๆœฌ็‰‡ๆฎต๏ผ‰ใ€‚ +- ๆ–ฐๅขž `length`๏ผˆไธ‰ๆฎต token ้•ฟๅบฆ๏ผ‰๏ผš`[in, cot, out]`๏ผŒๅนถไฟ่ฏไธŽ `span_in/span_cot/span_out` ๅฏน้ฝใ€‚ +- `hop` ๅญ—ๆฎต้‡‡็”จโ€œ้ป˜่ฎค็ญ–็•ฅโ€๏ผšๅฝ“ trace ๆ ทๆœฌไธญๅญ˜ๅœจ `vh` ๆ—ถๆ‰่พ“ๅ‡บ `hop`๏ผ›ๅฆๅˆ™ไธ่พ“ๅ‡บไธ”ไธๆŠฅ้”™ใ€‚ +- ๆ”ฏๆŒไธ€ๆฌกๆ€งๅค„็† `exp/exp2/output/traces/` ไธ‹ๆ‰€ๆœ‰ run ็›ฎๅฝ•๏ผˆๆ‰€ๆœ‰ๆ•ฐๆฎ้›†-ๆ–นๆณ•็ป„ๅˆ๏ผ‰ใ€‚ + +--- + +## ่พ“ๅ…ฅ็ป“ๆž„๏ผˆexp2 traces๏ผ‰ + +`exp2` ็š„ trace run ็›ฎๅฝ•ๅฝขๅฆ‚๏ผš +- `exp/exp2/output/traces////` + +ๆฏไธช run ็›ฎๅฝ•ๅŒ…ๅซ๏ผš +- `manifest.jsonl`๏ผˆๆฏ่กŒไธ€ไธชๆ ทๆœฌ่ฎฐๅฝ•๏ผŒๅŒ…ๅซ `file=ex_*.npz`๏ผ‰ +- `ex_*.npz`๏ผˆๆฏๆ ทๆœฌไธ€ไธช npz๏ผ‰ + +--- + +## ่พ“ๅ‡บไฝ็ฝฎไธŽๅ‘ฝๅ + +้ป˜่ฎค่พ“ๅ‡บๅˆฐ๏ผš +- `exp/proc_1/output//` + +ไพ‹ๅฆ‚่พ“ๅ…ฅ๏ผš +- `.../output/traces/exp/exp2/data/math.jsonl/qwen-8B//` + +้ป˜่ฎค่พ“ๅ‡บ๏ผš +- `exp/proc_1/output/exp/exp2/data/math.jsonl/qwen-8B//` + +--- + +## ่พ“ๅ‡บ `.npz` ๅญ—ๆฎต + +ๆฏไธช่พ“ๅ‡บๆ ทๆœฌ `.npz` ไป…ๅŒ…ๅซไธ‹ๅˆ—้”ฎ๏ผš +- `attr`๏ผš`float32[L]`๏ผŒrow ๅฝ’ๅ› ๅ‘้‡๏ผ›่ฆ†็›– `input+cot+output` ็š„ๆœ‰ๆ•ˆ token๏ผˆ็งป้™ค generation ๆœซๅฐพ EOS๏ผ‰ใ€‚ +- `hop`๏ผš`float32[H, L]`๏ผˆๅฏ้€‰๏ผ‰๏ผŒๅฝ“ trace npz ไธญๅญ˜ๅœจ `vh` ๆ—ถ่พ“ๅ‡บ๏ผˆๅŒๆ ท็งป้™ค EOS๏ผŒๅนถไธŽ `attr` ็ญ‰้•ฟๅฏน้ฝ๏ผ‰ใ€‚ +- `span_in`๏ผš`int64[2]`๏ผŒinput ๅœจๅ‘้‡ไธญ็š„้—ญๅŒบ้—ด่Œƒๅ›ดใ€‚ +- `span_cot`๏ผš`int64[2]`๏ผŒcot ๅœจๅ‘้‡ไธญ็š„้—ญๅŒบ้—ด่Œƒๅ›ด๏ผˆๆ—  cot ๆ—ถไธบ `[-1, -1]`๏ผ‰ใ€‚ +- `span_out`๏ผš`int64[2]`๏ผŒoutput ๅœจๅ‘้‡ไธญ็š„้—ญๅŒบ้—ด่Œƒๅ›ดใ€‚ +- `length`๏ผš`int64[3]`๏ผŒ้กบๅบไธบ `[in, cot, out]`๏ผŒ้•ฟๅบฆไธŽ `span_*` ไธฅๆ ผๅฏนๅบ”๏ผˆ้—ญๅŒบ้—ด้•ฟๅบฆ `end-start+1`๏ผŒ็ฉบ span ้•ฟๅบฆไธบ 0๏ผ‰ใ€‚ +- `rise`๏ผš`float64`๏ผŒrow ็š„ RISE๏ผˆfaithfulness๏ผ‰ใ€‚ +- `mas`๏ผš`float64`๏ผŒrow ็š„ MAS๏ผˆfaithfulness๏ผ‰ใ€‚ +- `recovery`๏ผš`float64`๏ผŒrow ็š„ Recovery@10%๏ผˆๆฒกๆœ‰ recovery ๆ—ถไธบ NaN๏ผ‰ใ€‚ + +--- + +## ็”จๆณ•็คบไพ‹ + +ๅค„็† traces ไธ‹ๆ‰€ๆœ‰ run๏ผˆๆŽจ่๏ผ‰๏ผš +```bash +python exp/proc_1/map_exp2_traces_to_proc_1.py \ + --traces_root exp/exp2/output/traces +``` + +ๅชๅค„็†ๆŸไธ€ไธช run ็›ฎๅฝ•๏ผš +```bash +python exp/proc_1/map_exp2_traces_to_proc_1.py \ + --trace_dir exp/exp2/output/traces/exp/exp2/data/math.jsonl/qwen-8B/ifr_multi_hop_both_n1_mfaithfulness_gen_100ex +``` + +่ฐƒ่ฏ•๏ผšๆฏไธช run ๅชๅค„็†ๅ‰ 5 ๆกใ€ๅ…่ฎธ่ฆ†็›–่พ“ๅ‡บ๏ผš +```bash +python exp/proc_1/map_exp2_traces_to_proc_1.py \ + --traces_root exp/exp2/output/traces \ + --limit 5 \ + --overwrite +``` diff --git a/exp/proc_1/map_exp2_traces_to_proc_1.py b/exp/proc_1/map_exp2_traces_to_proc_1.py new file mode 100644 index 0000000000000000000000000000000000000000..54be366773bdf30fd32ec650e64ba469d9f2c98a --- /dev/null +++ b/exp/proc_1/map_exp2_traces_to_proc_1.py @@ -0,0 +1,338 @@ +#!/usr/bin/env python3 +"""Map exp2 trace artifacts into a collaborator-friendly per-sample NPZ format (proc_1). + +This is a lightweight variant of `exp/proc/map_exp2_traces_to_proc.py`: +- Removes `tok` (per-token text pieces). +- Adds `length` with three components [in, cot, out], aligned to span_in/span_cot/span_out. +- Saves `hop` only when the trace sample contains `vh` (default strategy). +- Can process a single exp2 trace run directory or all run directories under a traces root. + +Input: an exp2 trace run directory produced by `exp/exp2/run_exp.py --save_hop_traces`, e.g.: + + exp/exp2/output/traces/exp/exp2/data/math.jsonl/qwen-8B/ifr_multi_hop_both_n1_mfaithfulness_gen_100ex/ + +This directory contains: + - manifest.jsonl (one JSON object per sample) + - ex_*.npz (per-sample vectors and scores) + +Output: per-sample NPZ files under `exp/proc_1/output/` (or a user-provided output path), +each containing only: + - attr: row attribution vector over [input + CoT + output] tokens, with EOS removed + - hop: per-hop vectors (optional; only if `vh` exists in the trace npz), aligned to attr + - span_in/span_cot/span_out: inclusive ranges for input/CoT/output in the above vectors + - length: int64[3] = [in, cot, out], derived strictly from spans + - rise/mas: row faithfulness scores (RISE, MAS) + - recovery: row Recovery@10% score (NaN when unavailable) + +This script is intentionally self-contained under exp/proc_1/ and does not modify exp2. +""" + +from __future__ import annotations + +import argparse +import json +from dataclasses import dataclass +from pathlib import Path +from typing import Iterable, List, Optional, Tuple + +import numpy as np + + +def _infer_trace_suffix(trace_dir: Path) -> Optional[Path]: + parts = list(trace_dir.parts) + if "traces" not in parts: + return None + idx = parts.index("traces") + suffix_parts = parts[idx + 1 :] + if not suffix_parts: + return None + return Path(*suffix_parts) + + +def _iter_run_dirs(traces_root: Path) -> List[Path]: + runs = {p.parent for p in traces_root.rglob("manifest.jsonl") if p.is_file()} + return sorted(runs) + + +def _parse_manifest(manifest_path: Path) -> List[dict]: + records: List[dict] = [] + with manifest_path.open("r", encoding="utf-8") as f: + for line in f: + if not line.strip(): + continue + records.append(json.loads(line)) + return records + + +def _read_span(npz: np.lib.npyio.NpzFile, key: str) -> Optional[Tuple[int, int]]: + if key not in npz.files: + return None + arr = npz[key] + if arr.shape != (2,): + raise ValueError(f"Expected {key} to have shape (2,), got {arr.shape}.") + return int(arr[0]), int(arr[1]) + + +def _clamp_span(span: Optional[Tuple[int, int]], *, max_index: int) -> Optional[Tuple[int, int]]: + if span is None: + return None + start, end = int(span[0]), int(span[1]) + if max_index < 0: + return None + if end < 0 or start > max_index: + return None + start = max(0, start) + end = min(max_index, end) + if end < start: + return None + return start, end + + +def _span_len(span: Tuple[int, int]) -> int: + start, end = int(span[0]), int(span[1]) + if start < 0 or end < 0 or end < start: + return 0 + return int(end - start + 1) + + +@dataclass(frozen=True) +class ProcOneResult: + wrote: bool + has_hop: bool + + +def _proc_one( + *, + trace_npz_path: Path, + record: dict, + out_path: Path, + overwrite: bool, +) -> ProcOneResult: + if out_path.exists() and not overwrite: + raise FileExistsError(f"Refusing to overwrite existing file: {out_path} (use --overwrite).") + out_path.parent.mkdir(parents=True, exist_ok=True) + + with np.load(trace_npz_path, allow_pickle=False) as f: + prompt_len = int(np.asarray(f.get("prompt_len")).item()) + gen_len = int(np.asarray(f.get("gen_len")).item()) + total_len = prompt_len + gen_len + gen_no_eos = max(0, gen_len - 1) + L = prompt_len + gen_no_eos + + v_row_all = f.get("v_row_all") + if v_row_all is None: + raise ValueError("Missing v_row_all in trace npz; cannot build row attribution vector.") + v_row_all = np.asarray(v_row_all, dtype=np.float32) + if v_row_all.ndim != 1 or int(v_row_all.shape[0]) != int(total_len): + raise ValueError(f"v_row_all shape mismatch: expected ({total_len},), got {tuple(v_row_all.shape)}.") + attr = v_row_all[:L] + + indices_to_explain = _read_span(f, "indices_to_explain_gen") + sink_span_gen = _read_span(f, "sink_span_gen") or indices_to_explain + if sink_span_gen is None: + raise ValueError("Missing sink_span_gen/indices_to_explain_gen; cannot define output span.") + thinking_span_gen = _read_span(f, "thinking_span_gen") + if thinking_span_gen is None: + sink_start = int(sink_span_gen[0]) + think_end = sink_start - 1 + thinking_span_gen = (0, think_end) if think_end >= 0 else None + + sink_span_gen = _clamp_span(sink_span_gen, max_index=gen_no_eos - 1) + thinking_span_gen = _clamp_span(thinking_span_gen, max_index=gen_no_eos - 1) + + span_in = (0, prompt_len - 1) if prompt_len > 0 else (-1, -1) + span_cot = ( + (prompt_len + thinking_span_gen[0], prompt_len + thinking_span_gen[1]) + if thinking_span_gen is not None + else (-1, -1) + ) + span_out = ( + (prompt_len + sink_span_gen[0], prompt_len + sink_span_gen[1]) if sink_span_gen is not None else (-1, -1) + ) + + length = np.asarray([_span_len(span_in), _span_len(span_cot), _span_len(span_out)], dtype=np.int64) + + rise = float("nan") + mas = float("nan") + faith = f.get("faithfulness_scores") + if faith is not None: + faith = np.asarray(faith, dtype=np.float64) + if faith.shape != (3, 3): + raise ValueError(f"faithfulness_scores shape mismatch: expected (3,3), got {tuple(faith.shape)}.") + rise = float(faith[1, 0]) + mas = float(faith[1, 1]) + + recovery = float("nan") + rec = f.get("recovery_scores") + if rec is not None: + rec = np.asarray(rec, dtype=np.float64) + if rec.shape != (3,): + raise ValueError(f"recovery_scores shape mismatch: expected (3,), got {tuple(rec.shape)}.") + recovery = float(rec[1]) + + out_payload = { + "attr": np.asarray(attr, dtype=np.float32), + "span_in": np.asarray(span_in, dtype=np.int64), + "span_cot": np.asarray(span_cot, dtype=np.int64), + "span_out": np.asarray(span_out, dtype=np.int64), + "length": np.asarray(length, dtype=np.int64), + "rise": np.asarray(rise, dtype=np.float64), + "mas": np.asarray(mas, dtype=np.float64), + "recovery": np.asarray(recovery, dtype=np.float64), + } + + has_hop = False + vh = f.get("vh") + if vh is not None: + vh = np.asarray(vh, dtype=np.float32) + if vh.ndim != 2 or int(vh.shape[1]) != int(total_len): + raise ValueError(f"vh shape mismatch: expected (H,{total_len}), got {tuple(vh.shape)} for {trace_npz_path}.") + out_payload["hop"] = vh[:, :L] + has_hop = True + + np.savez_compressed(out_path, **out_payload) + _ = record + return ProcOneResult(wrote=True, has_hop=has_hop) + + +def _resolve_out_dir_for_trace_dir(*, trace_dir: Path, out_root: Path, out_dir: Optional[Path]) -> Path: + if out_dir is not None: + return out_dir + suffix = _infer_trace_suffix(trace_dir) + return (out_root / suffix) if suffix is not None else (out_root / trace_dir.name) + + +def _process_trace_dir( + *, + trace_dir: Path, + out_root: Path, + out_dir: Optional[Path], + overwrite: bool, + limit: Optional[int], + skip_empty_manifest: bool, +) -> Tuple[int, int]: + manifest_path = trace_dir / "manifest.jsonl" + if not manifest_path.exists(): + raise SystemExit(f"Missing manifest.jsonl: {manifest_path}") + + records = _parse_manifest(manifest_path) + if not records: + if skip_empty_manifest: + print(f"[skip] empty manifest: {manifest_path}") + return 0, 0 + raise SystemExit(f"Empty manifest.jsonl: {manifest_path}") + + total = len(records) + if limit is not None: + if limit <= 0: + raise SystemExit("--limit must be a positive integer.") + total = min(total, int(limit)) + + resolved_out_dir = _resolve_out_dir_for_trace_dir(trace_dir=trace_dir, out_root=out_root, out_dir=out_dir) + resolved_out_dir.mkdir(parents=True, exist_ok=True) + + wrote = 0 + wrote_with_hop = 0 + for record in records[:total]: + file_name = str(record.get("file") or "") + if not file_name: + raise SystemExit("manifest record missing 'file' field.") + trace_npz_path = trace_dir / file_name + if not trace_npz_path.exists(): + raise SystemExit(f"Missing trace npz referenced by manifest: {trace_npz_path}") + + out_path = resolved_out_dir / file_name + try: + res = _proc_one(trace_npz_path=trace_npz_path, record=record, out_path=out_path, overwrite=overwrite) + except Exception as exc: + raise SystemExit(f"Failed processing {trace_npz_path}: {exc}") from exc + wrote += int(res.wrote) + wrote_with_hop += int(res.has_hop) + + print(f"[ok] wrote {wrote} samples ({wrote_with_hop} with hop) -> {resolved_out_dir}") + return wrote, wrote_with_hop + + +def main() -> None: + ap = argparse.ArgumentParser("Map exp2 trace folder(s) -> exp/proc_1/output per-sample npz files.") + ap.add_argument( + "--trace_dir", + type=str, + default=None, + help="Path to a single exp2 trace run directory (contains manifest.jsonl).", + ) + ap.add_argument( + "--traces_root", + type=str, + default=None, + help="Path to traces root; processes all run dirs under it (each with a manifest.jsonl).", + ) + ap.add_argument("--out_root", type=str, default="exp/proc_1/output", help="Root directory for proc_1 outputs.") + ap.add_argument( + "--out_dir", + type=str, + default=None, + help="Optional explicit output directory (only valid with --trace_dir; overrides --out_root).", + ) + ap.add_argument("--overwrite", action="store_true", help="Overwrite existing output files if present.") + ap.add_argument("--limit", type=int, default=None, help="Optional limit on number of samples per run (debug).") + ap.add_argument( + "--fail_on_empty_manifest", + action="store_true", + help="Fail (instead of skipping) when encountering an empty manifest.jsonl.", + ) + args = ap.parse_args() + + trace_dir = Path(args.trace_dir) if args.trace_dir else None + traces_root = Path(args.traces_root) if args.traces_root else None + if (trace_dir is None) == (traces_root is None): + raise SystemExit("Please pass exactly one of --trace_dir or --traces_root.") + + out_root = Path(args.out_root) + out_dir = Path(args.out_dir) if args.out_dir else None + if out_dir is not None and trace_dir is None: + raise SystemExit("--out_dir is only valid with --trace_dir (for --traces_root use --out_root).") + + skip_empty_manifest = not bool(args.fail_on_empty_manifest) + + if trace_dir is not None: + if not trace_dir.exists() or not trace_dir.is_dir(): + raise SystemExit(f"Missing trace_dir: {trace_dir}") + _process_trace_dir( + trace_dir=trace_dir, + out_root=out_root, + out_dir=out_dir, + overwrite=bool(args.overwrite), + limit=args.limit, + skip_empty_manifest=skip_empty_manifest, + ) + return + + assert traces_root is not None + if not traces_root.exists() or not traces_root.is_dir(): + raise SystemExit(f"Missing traces_root: {traces_root}") + + run_dirs = _iter_run_dirs(traces_root) + if not run_dirs: + raise SystemExit(f"No run directories found under traces_root={traces_root} (expected manifest.jsonl).") + + total_written = 0 + total_with_hop = 0 + for run_dir in run_dirs: + wrote, wrote_with_hop = _process_trace_dir( + trace_dir=run_dir, + out_root=out_root, + out_dir=None, + overwrite=bool(args.overwrite), + limit=args.limit, + skip_empty_manifest=skip_empty_manifest, + ) + total_written += wrote + total_with_hop += wrote_with_hop + + print(f"[done] total wrote {total_written} samples ({total_with_hop} with hop) under out_root={out_root}") + + +if __name__ == "__main__": + main() + diff --git a/flashtrace/__init__.py b/flashtrace/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..965b43ea5854afd0cb94b273883c996ab16b4383 --- /dev/null +++ b/flashtrace/__init__.py @@ -0,0 +1,7 @@ +"""FlashTrace: efficient multi-token attribution for reasoning LLMs.""" + +from .model_io import load_model_and_tokenizer +from .result import TokenScore, TraceResult +from .tracer import FlashTrace + +__all__ = ["FlashTrace", "TraceResult", "TokenScore", "load_model_and_tokenizer"] diff --git a/flashtrace/attribution.py b/flashtrace/attribution.py new file mode 100644 index 0000000000000000000000000000000000000000..dcdca4dc2e1ab111d8c8c220d77e458b1ddabf18 --- /dev/null +++ b/flashtrace/attribution.py @@ -0,0 +1,2975 @@ +import matplotlib +import matplotlib.cm as mpl_cm +from matplotlib import pyplot as plt +import numpy as np +import torch + +if not hasattr(mpl_cm, "register_cmap"): + from matplotlib import colors as _mpl_colors + + def _register_cmap(name=None, cmap=None, data=None, lut=None, *, force=False): + """Compatibility wrapper for Matplotlib >=3.10 where register_cmap moved.""" + if cmap is not None and data is not None: + raise ValueError("Cannot specify both `cmap` and `data` when registering a colormap.") + if data is not None: + if name is None: + raise ValueError("Must supply a name when registering colormap data.") + cmap = _mpl_colors.LinearSegmentedColormap(name, data, lut=lut) + elif cmap is None: + raise ValueError("Must supply `cmap` or `data` when registering a colormap.") + + if isinstance(cmap, str): + cmap = mpl_cm.get_cmap(cmap) + + name = name or cmap.name + copied = cmap.copy() + copied.name = name + mpl_cm._colormaps.register(copied, name=name, force=force) + + def _unregister_cmap(name): + mpl_cm._colormaps.unregister(name) + + mpl_cm.register_cmap = _register_cmap + mpl_cm.unregister_cmap = _unregister_cmap + +import seaborn as sns +import torch.nn as nn +import torch.nn.functional as F +from tqdm import tqdm +from typing import Dict, Any, List, Optional, Tuple, Sequence +import textwrap +from transformers import LongformerTokenizer, LongformerForMaskedLM +import networkx as nx +import matplotlib as mpl +from matplotlib.patches import FancyArrowPatch +from wordfreq import zipf_frequency + +from dataclasses import dataclass +from typing import Literal + +from .core import ( + IFRParameters, + ModelMetadata, + attach_hooks, + build_weight_pack, + compute_ifr_for_all_positions, + compute_ifr_sentence_aggregate, + compute_multi_hop_ifr, + extract_model_metadata, +) + + +@dataclass +class AttnLRPSpanAggregate: + """Span-wise aggregated AttnLRP result (single vector), analogous to IFRAggregate. + + This dataclass stores the result of span-wise AttnLRP aggregation computed + in O(N) time using a single forward + backward pass. + + Attributes + ---------- + token_importance_total : torch.Tensor + 1D float32 CPU tensor of length (user_prompt_len + gen_len) after + chat-template stripping, aligned with `all_tokens`. + all_tokens : List[str] + All tokens (user prompt + generation) + user_prompt_tokens : List[str] + User prompt tokens only + generation_tokens : List[str] + Generation tokens only + sink_range : Tuple[int, int] + [sink_start, sink_end] in generation-token indices + sink_weights : Optional[torch.Tensor] + Weights used for aggregation (if any) + metadata : Dict[str, Any] + Additional metadata about the computation + """ + token_importance_total: torch.Tensor + all_tokens: List[str] + user_prompt_tokens: List[str] + generation_tokens: List[str] + sink_range: Tuple[int, int] + sink_weights: Optional[torch.Tensor] + metadata: Dict[str, Any] + + +@dataclass +class MultiHopAttnLRPResult: + """Multi-hop AttnLRP attribution result, analogous to MultiHopIFRResult. + + This dataclass stores the result of multi-hop AttnLRP computation where + attribution is recursively propagated from output โ†’ thinking โ†’ input. + + Attributes + ---------- + raw_attributions : List[AttnLRPSpanAggregate] + List of per-hop attribution results. Index 0 is the base (outputโ†’all), + subsequent indices are hop 1, 2, etc. (thinkingโ†’all with weights). + thinking_ratios : List[float] + Fraction of attribution mass on the thinking span at each hop. + Useful for understanding how much attribution "stays" in reasoning. + observation : Dict[str, torch.Tensor] + Dictionary containing: + - "mask": observation mask (1 for observable tokens, 0 for thinking/sink) + - "base": base attribution masked to observable tokens + - "per_hop": list of per-hop attributions masked to observable tokens + - "sum": cumulative sum of all per-hop observations + - "avg": average of per-hop observations + """ + raw_attributions: List[AttnLRPSpanAggregate] + thinking_ratios: List[float] + observation: Dict[str, torch.Tensor] + + +from .shared_utils import ( + DEFAULT_GENERATE_KWARGS, + DEFAULT_PROMPT_TEMPLATE, + create_sentences, + create_sentence_masks, +) + +from .lrp_patches import lrp_context, detect_model_type + +matplotlib.rcParams['text.usetex'] = False +matplotlib.rcParams['mathtext.default'] = 'regular' + +class LLMAttribution(): + def __init__( + self, + model: Any, + tokenizer: Any, + generate_kwargs: Optional[Dict[str, Any]] = None, + *, + use_chat_template: bool = False, + ) -> None: + + self.model = model + self.tokenizer = tokenizer + self.device = model.device + + self.generate_kwargs = generate_kwargs or DEFAULT_GENERATE_KWARGS + self.use_chat_template = bool(use_chat_template) + + self.prompt = None + self.prompt_ids = None + self.prompt_tokens = None + self.chat_prompt_indices = None + + self.user_prompt = None + self.user_prompt_ids = None + self.user_prompt_tokens = None + self.user_prompt_indices = None + + self.generation = None + self.generation_ids = None + self.generation_tokens = None + + self.model.eval() + + def decode_text_into_tokens(self, text) -> list[str]: + encoding = self.tokenizer(text, return_offsets_mapping=True, add_special_tokens=False) + + ids = encoding["input_ids"] + offsets = encoding["offset_mapping"] + + text_tokens = [] + offsets = list(offsets) + for i in range(len(ids)): + span = offsets.pop(0) + start, end = span + actual_text = text[start:end] + text_tokens.append(actual_text) + + return text_tokens + + def extract_user_prompt_attributions(self, input, attribution) -> list[str]: + # Extract all attributions to be kept (gen -> user prompt and gen -> gen attributions) + user_prompt_attr_idx = torch.tensor(self.user_prompt_indices) + gen_attr_idx = torch.arange(len(input), attribution.shape[1]) + all_keep_idx = torch.cat((user_prompt_attr_idx, gen_attr_idx), dim = 0) + + return attribution[:, all_keep_idx] + + # Takes a torch tensor of size [N, M] and extends it to [N, target_length] with a padding value + def pad_vector(self, vector, target_length, padding_value = 0) -> torch.Tensor: + current_length = vector.shape[1] + if current_length >= target_length: + return vector + padding_size = target_length - current_length + padded_vector = F.pad(vector, (0, padding_size), value=padding_value) + return padded_vector + + def format_prompt(self, prompt) -> str: + if not self.use_chat_template: + return prompt + + modified_prompt = DEFAULT_PROMPT_TEMPLATE.format(context = prompt, query = "") + formatted_prompt = [{"role": "user", "content": modified_prompt}] + formatted_prompt = self.tokenizer.apply_chat_template( + formatted_prompt, + tokenize=False, + add_generation_prompt=True, + enable_thinking=False + ) + + return formatted_prompt + + # Query the model for its generation + # This internally saves the input and generated token ids for attribution target + def response(self, prompt) -> str: + self.user_prompt = " " + prompt if self.use_chat_template else prompt + self.prompt = self.format_prompt(self.user_prompt) + + # these are the ids for the user supplied prompt + self.user_prompt_ids = self.tokenizer(self.user_prompt, return_tensors="pt", add_special_tokens = False).to(self.device).input_ids + # this is the tokenization of the chat prompt + self.prompt_ids = self.tokenizer(self.prompt, return_tensors="pt", add_special_tokens = False).to(self.device).input_ids + + with torch.no_grad(): + outputs = self.model.generate(self.prompt_ids, **self.generate_kwargs) # [1, num_prompt_tokens + num_generations] + + # Get only the generated tokens (excluding the prompt) + self.generation_ids = outputs[:, self.prompt_ids.shape[1]:] # [1, num_generations] + self.generation = self.tokenizer.decode(self.generation_ids[0], skip_special_tokens = True) + gen_with_eos = self.tokenizer.decode(self.generation_ids[0], skip_special_tokens = False, clean_up_tokenization_spaces = False) + + # we want to find the indices of the formatted prompt that the user prompt occupies + # we only want to attribute the user prompt, so we track this for later + n, m = len(self.user_prompt_ids[0]), len(self.prompt_ids[0]) + for i, input_id in enumerate(self.prompt_ids[0]): + if input_id == self.user_prompt_ids[0, 0]: + self.user_prompt_indices = list(range(i, i + n)) + break + + # make a list of indices which are all prompt tokens + # (chat prompt formatting) that are not the user prompt tokens + self.chat_prompt_indices = [idx for idx in range(0, m) if idx < self.user_prompt_indices[0] or idx > self.user_prompt_indices[-1]] + + # get the full prompt, user prompt, and generation as tokenized words + self.prompt_tokens = self.decode_text_into_tokens(self.prompt) + # print(self.prompt_tokens) + self.user_prompt_tokens = self.decode_text_into_tokens(self.user_prompt) + # print(self.user_prompt_tokens) + self.generation_tokens = self.decode_text_into_tokens(gen_with_eos) + # print(self.generation_tokens) + + return self.generation + + # nearly identical to response(), but we do not actually query the model + # we assume generation = target, and generate all the class variables as done in response() + def target_response(self, prompt, target) -> str: + self.user_prompt = " " + prompt if self.use_chat_template else prompt + self.prompt = self.format_prompt(self.user_prompt) + + # these are the ids for the user supplied prompt + self.user_prompt_ids = self.tokenizer(self.user_prompt, return_tensors="pt", add_special_tokens = False).to(self.device).input_ids + # this is the tokenization of the chat prompt + self.prompt_ids = self.tokenizer(self.prompt, return_tensors="pt", add_special_tokens = False).to(self.device).input_ids # [1, num_prompt_tokens] + # Tokenize the target generation + target_text = target + (self.tokenizer.eos_token or "") + self.generation_ids = self.tokenizer(target_text, return_tensors="pt", add_special_tokens = False).to(self.device).input_ids # [1, num_generations] + self.generation = target + gen_with_eos = self.tokenizer.decode(self.generation_ids[0], skip_special_tokens = False, clean_up_tokenization_spaces = False) + + # we want to find which indices of the formatted prompt that the user prompt occupies + # we will only want to attribute the user prompt, so we track this for later + n, m = len(self.user_prompt_ids[0]), len(self.prompt_ids[0]) + for i, input_id in enumerate(self.prompt_ids[0]): + if input_id == self.user_prompt_ids[0, 0]: + self.user_prompt_indices = list(range(i, i + n)) + break + + # make a list of indices which are all prompt tokens + # (chat prompt formatting) that are not the user prompt tokens + self.chat_prompt_indices = [idx for idx in range(0, m) if idx < self.user_prompt_indices[0] or idx > self.user_prompt_indices[-1]] + + # get the full prompt, user prompt, and generation as tokenized words + self.prompt_tokens = self.decode_text_into_tokens(self.prompt) + self.user_prompt_tokens = self.decode_text_into_tokens(self.user_prompt) + self.generation_tokens = self.decode_text_into_tokens(gen_with_eos) + + return self.generation + +class LLMAttributionResult(): + def __init__( + self, + tokenizer: Any, + attribution_matrix: torch.Tensor, + prompt_tokens: list[str], + generation_tokens: list[str], + all_tokens: Optional[list[str]] = None, + metadata: Optional[Dict[str, Any]] = None, + ) -> None: + + self.tokenizer = tokenizer + + self.prompt_tokens = prompt_tokens + self.generation_tokens = generation_tokens + self.all_tokens = all_tokens + if self.all_tokens is not None: + self.all_tokens = self.all_tokens + + self.attribution_matrix = attribution_matrix.detach().cpu() + self.metadata = metadata + + # normalize rows of a matrix to sum to 1 + def normalize_sum_to_one(self, attriubtion_matrix) -> torch.Tensor: + # we use nans for visualization, but they must be removed (set to 0) for this function + attribution_no_nan = torch.nan_to_num(attriubtion_matrix, nan=0.0) + # we do not want to include negative attributions, clamp all to 0 + attribution_no_nan = attribution_no_nan.clamp(0) + # first, normalize the rows of the attribution matrix to sum to one + attribution_row_sums = attribution_no_nan.sum(1, keepdim=True) + 1e-8 + # perform normalization + return attribution_no_nan / attribution_row_sums + + def remove_nan(self, attriubtion_matrix) -> torch.Tensor: + # we use nans for visualization, but they must be removed (set to 0) for this function + attribution_no_nan = torch.nan_to_num(attriubtion_matrix, nan=0.0) + # we do not want to include negative attributions, clamp all to 0 + attribution_no_nan = attribution_no_nan.clamp(0) + return attribution_no_nan + + # normalize the max of a vector to 1 + def normalize_max(self, attribution_vector) -> torch.Tensor: + if attribution_vector.max() > 0: + attribution_vector = attribution_vector / attribution_vector.max() + elif attribution_vector.max() <= 0: + attribution_vector = - attribution_vector / attribution_vector.min() + + return attribution_vector + + ########################################## token attr ########################################## + + def compute_CAGE_token_attr( + self, + token_to_explain: int, + *, + clear_values: bool = True, + token_attr_matrix_norm: Optional[torch.Tensor] = None, + ) -> torch.Tensor: + """Token-level CAGE-style recursive attribution over a token attribution matrix. + + token_to_explain is a generation-token index in [0, G). + """ + attr_norm = ( + token_attr_matrix_norm + if token_attr_matrix_norm is not None + else self.normalize_sum_to_one(self.attribution_matrix) + ) + + prompt_len = len(self.prompt_tokens) + gen_len = len(self.generation_tokens) + expected_cols = prompt_len + gen_len + if attr_norm.ndim != 2 or attr_norm.shape[0] != gen_len or attr_norm.shape[1] != expected_cols: + raise TypeError( + "Expected token attribution matrix of shape [G, P+G] where " + f"G={gen_len} and P={prompt_len}, got {tuple(attr_norm.shape)}." + ) + if token_to_explain < 0 or token_to_explain >= gen_len: + raise IndexError(f"token_to_explain out of range: {token_to_explain} not in [0, {gen_len}).") + + r = attr_norm[token_to_explain, :].clone() + for k in range(token_to_explain - 1, -1, -1): + alpha = r[prompt_len + k] + if alpha != 0: + r += attr_norm[k, :] * alpha + if clear_values: + r[prompt_len + k] = 0 + return r + + def get_all_token_attrs(self, indices_to_explain: List[int]) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: + """Return token-level (seq, row, rec) attributions. + + indices_to_explain must be a generation-token span [start_tok, end_tok] + (closed interval), typically pointing to the \\box{...} inner answer span. + """ + if not isinstance(indices_to_explain, list) or len(indices_to_explain) != 2: + raise ValueError( + "indices_to_explain must be a token span [start_tok, end_tok] " + f"(got {indices_to_explain!r})." + ) + start_tok, end_tok = indices_to_explain + if not isinstance(start_tok, int) or not isinstance(end_tok, int): + raise TypeError(f"indices_to_explain elements must be ints (got {indices_to_explain!r}).") + if start_tok < 0 or end_tok < 0 or start_tok > end_tok: + raise ValueError(f"Invalid token span: {indices_to_explain!r}.") + + attr_norm = self.normalize_sum_to_one(self.attribution_matrix) + gen_len = int(attr_norm.shape[0]) + if end_tok >= gen_len: + raise IndexError(f"end_tok out of range: {end_tok} >= G={gen_len}.") + + seq_attr = attr_norm + row_attr = attr_norm[start_tok : end_tok + 1, :].sum(dim=0, keepdim=True) + + rec_sum = torch.zeros_like(row_attr) + for t in range(start_tok, end_tok + 1): + rec_sum += self.compute_CAGE_token_attr( + t, + clear_values=True, + token_attr_matrix_norm=attr_norm, + ).reshape(1, -1) + rec_attr = rec_sum + + return seq_attr, row_attr, rec_attr + + ########################################## sentence attr ########################################## + + # This converts any token attribution to a sentence attribution + def compute_sentence_attr(self, norm = True) -> None: + raise RuntimeError("Sentence-level aggregation has been removed; use token-level get_all_token_attrs().") + + # Legacy implementation (kept for reference) + # create the prompt ang generation sentences + self.prompt_sentences = create_sentences("".join(self.prompt_tokens), self.tokenizer) + self.generation_sentences = create_sentences("".join(self.generation_tokens), self.tokenizer) + self.all_sentences = self.prompt_sentences + self.generation_sentences + + # create a mask that tracks the tokens used in each sentence of the generation + sentence_masks_generation = create_sentence_masks(self.generation_tokens, self.generation_sentences) + # create a mask that tracks the tokens used in each sentence of the prompt and the generation + sentence_masks_all = create_sentence_masks(self.prompt_tokens + self.generation_tokens, self.all_sentences) + + num_inp_sent = len(self.prompt_sentences) + num_gen_sent = len(self.generation_sentences) + num_all_sent = len(self.all_sentences) + + # Now we want to turn our attribution which is over tokens into an attribution over sentences + # attribution rows = gen sentences + # attribution columns = prompt sentences + gen sentences + self.sentence_attr = torch.full((num_gen_sent, num_all_sent), torch.nan) + for i in range(num_gen_sent): + # Select the rows (sentence) of the matrix which are attributed to the inputs (cols) + # A whole sentence is selected at once + row_indices = torch.where(sentence_masks_generation[i] == 1)[0] + attr_rows = self.attribution_matrix[row_indices, :] + + for j in range(num_all_sent): + # we do not attribute a generation to itself or any + # future generations so we can skip those here + if j > i + num_inp_sent - 1: + continue + + # now we select the columns + col_indices = torch.where(sentence_masks_all[j] == 1)[0] + + # now select a whole sentence of cols from these rows + attr = attr_rows[:, col_indices] + + # Find which of these indices are NaN + nan_mask = torch.isnan(attr) + # Replace NaNs with 0 + attr[nan_mask] = 0.0 + + # take sum of this 2d attr and place it in the correct + # spot of the sentence attribution + self.sentence_attr[i, j] = torch.sum(attr) + + if norm: + self.sentence_attr = self.normalize_sum_to_one(self.sentence_attr) + else: + self.sentence_attr = self.remove_nan(self.sentence_attr) + + return + + def plot_attr_table_sentence(self, height = None) -> None: + if self.sentence_attr is None: + print( + '''The sentence attribution has not been computed. + Call LLMAttributionResult.compute_sentence_attr() first. + ''' + ) + return + + width = 15 + wrapped_sentences_x = [] + for sentence in self.all_sentences: + wrapped_sentences_x.append(textwrap.fill(sentence, width=width)) + wrapped_sentences_y = [] + max_num_lines = 0 + for sentence in self.generation_sentences: + sentence = textwrap.fill(sentence, width=width) + num_lines = len(sentence.split("\n")) + max_num_lines = num_lines if num_lines > max_num_lines else max_num_lines + wrapped_sentences_y.append(sentence) + + + fig_width = (len(self.all_sentences) * width / 10) if (len(self.all_sentences) * width / 10) > 10 else 10 + if height is None: + fig_height = (len(self.generation_sentences) * max_num_lines / 8) if (len(self.generation_sentences) * max_num_lines / 8) > 8 else 8 + else: + fig_height = 5 + + fig, axs = plt.subplots(1, 1, figsize = (fig_width, fig_height)) + + # use a positive only heatmap cmap + if np.nanmin(self.sentence_attr) >= 0: + sns.heatmap(self.sentence_attr, annot=False, xticklabels=wrapped_sentences_x, yticklabels=wrapped_sentences_y, cmap="Blues", ax = axs) + # use a postitive and negative heatmap cmap + else: + # set vmax vmin such that 0 is center value of color map + max_abs_attr_val = np.nanmax(self.sentence_attr.abs()) + sns.heatmap(self.sentence_attr, annot=False, xticklabels=wrapped_sentences_x, yticklabels=wrapped_sentences_y, vmax=max_abs_attr_val, vmin=-max_abs_attr_val, cmap="Blues", ax = axs) + + axs.tick_params(top=True, bottom=False, labeltop=True, labelbottom=False, labelsize=200 / len(self.all_sentences)) + plt.yticks(rotation=45) + plt.xticks(rotation=45) + plt.show() + + def plot_context_attr_sentence(self, title) -> None: + if self.sentence_attr is None: + print( + '''The sentence attribution has not been computed. + Call LLMAttributionResult.compute_sentence_attr() first. + ''' + ) + return + + wrapped_sentences = [] + width = 20 + for sentence in self.prompt_sentences: + wrapped_sentences.append(textwrap.fill(sentence, width=width)) + + fig_width = len(wrapped_sentences) * (width / 10) + fig_height = len(wrapped_sentences) / 2 if len(wrapped_sentences) / 2 > 3 else 3 + + plt.figure(figsize=(fig_width, fig_height)) + plt.bar(np.arange(len(wrapped_sentences)), self.normalize_max(torch.nansum(self.sentence_attr[:, :len(self.prompt_sentences)].cpu().detach(), dim = 0))) + plt.xticks(range(len(wrapped_sentences)), wrapped_sentences, rotation=0) + plt.ylabel("Influence") + plt.title(title) + plt.tight_layout() + plt.show() + + + def save_context_attr_sentence(self, prompt_sentences, path) -> None: + if self.sentence_attr is None: + print( + '''The sentence attribution has not been computed. + Call LLMAttributionResult.compute_sentence_attr() first. + ''' + ) + return + + wrapped_sentences = [] + width = 20 + for sentence in prompt_sentences: + wrapped_sentences.append(textwrap.fill(sentence, width=width)) + + fig_width = len(wrapped_sentences) * (width / 10) + fig_height = len(wrapped_sentences) / 2 if len(wrapped_sentences) / 2 > 3 else 3 + + fig, axs = plt.subplots(1, 1, figsize = (fig_width, fig_height)) + plt.bar(np.arange(len(wrapped_sentences)), self.normalize_max(torch.nansum(self.sentence_attr[:, :len(prompt_sentences)].cpu().detach(), dim = 0))) + plt.xticks(range(len(wrapped_sentences)), wrapped_sentences, rotation=0) + plt.ylabel("Influence") + plt.tight_layout() + plt.savefig(path + ".png", bbox_inches='tight', transparent = "False") + fig.clear() + plt.close(fig) + + + def draw_graph(self, cmap = plt.cm.Blues, wrap_width=20, thresh = 0.10, spacing = 4, arrow_mod = 1, rad = 0.3): + """ + Simplified one-row attribution graph: + - All tokens (prompts + generations) drawn in one horizontal row + - Directed weighted edges: generation -> input + """ + + grad_array = self.sentence_attr + outputs = self.all_sentences + generated = self.generation_sentences + + grad_array = grad_array.permute((1, 0)) # -> [outputs, generated] + attr_np = grad_array.cpu().numpy() if hasattr(grad_array, "cpu") else grad_array + attr_np = np.nan_to_num(attr_np, nan=0.0) + + G = nx.DiGraph() + prompt_len = len(outputs) - len(generated) + n_gen = len(generated) + + # Node ids + prompt_ids = [f"p_{i}" for i in range(prompt_len)] + gen_ids = [f"g_{j}" for j in range(n_gen)] + + # Add nodes + def add_node(node_id, label, ntype): + wrapped = textwrap.fill(label, width=wrap_width) + wrap_height = len(wrapped.split('\n')) + G.add_node(node_id, label=wrapped, type=ntype) + return wrap_height + + max_wrap_height = 0 + for i in range(prompt_len): + wrap_height = add_node(prompt_ids[i], outputs[i], "prompt") + if wrap_height > max_wrap_height: + max_wrap_height = wrap_height + for j in range(n_gen): + wrap_height = add_node(gen_ids[j], generated[j], "generated") + if wrap_height > max_wrap_height: + max_wrap_height = wrap_height + + def out_i_to_node(i): + return prompt_ids[i] if i < prompt_len else gen_ids[i - prompt_len] + + # Add edges gen -> output + for j in range(n_gen): + src = gen_ids[j] + for i in range(len(outputs)): + w = attr_np[i, j] if (i < attr_np.shape[0] and j < attr_np.shape[1]) else 0.0 + if w != 0.0: + G.add_edge(src, out_i_to_node(i), weight=w) + + + # --- layout: single row --- + y_row = 0.0 + pos = {} + all_nodes = prompt_ids + gen_ids + for idx, nid in enumerate(all_nodes): + pos[nid] = (idx * spacing, y_row) + + # --- figure --- + ncols = len(all_nodes) + fig_width = max(10, ncols * (spacing * 0.6)) + fig, ax = plt.subplots(figsize=(fig_width, 4), dpi = 300) + + # prune edges + edges = list(G.edges(data=True)) + weights = np.array([edata["weight"] for _, _, edata in edges]) + if weights.size > 0: + threshold = thresh * np.max(np.abs(weights)) # keep edges โ‰ฅ 5% of max weight + for (u, v, edata) in list(edges): # iterate over a copy + if abs(edata["weight"]) < threshold: + G.remove_edge(u, v) + + # visualization + edges = G.edges(data=True) # refresh edges after pruning + weights = np.array([edata["weight"] for _, _, edata in edges]) + if weights.size == 0: + weights = np.array([1]) # fallback if everything pruned + max_w = np.max(np.abs(weights)) + norm = mpl.colors.TwoSlopeNorm(vmin=-max_w, vcenter=0, vmax=max_w) \ + if np.min(weights) < 0 else mpl.colors.Normalize(vmin=0, vmax=max_w) + + # Draw nodes (larger font + padding) + for nid, (x, y) in pos.items(): + lbl = G.nodes[nid]["label"] + ntype = G.nodes[nid]["type"] + box_color = "#d4c1ffc8" if ntype == "prompt" else "#cfffcc" #cfe8ff + ax.annotate( + lbl, xy=(x, y), xytext=(x, y), + ha="center", va="center", fontsize=12, zorder=3, + bbox=dict(boxstyle="round,pad=0.6", facecolor=box_color, + edgecolor="gray", linewidth=1.2, alpha=1), + ) + + box_height = max_wrap_height / 4 + # Draw edges with curved arrows + for (u, v, edata) in edges: + x1, y1 = pos[u] + x2, y2 = pos[v] + + start = (x1, y1 - box_height) + end = (x2, y2 - box_height) + + w = edata["weight"] + color = cmap(norm(w)) + width = (1.5 * arrow_mod) + 5.0 * (abs(w) / max_w) + + arrow_rad = rad if x1 <= x2 else -rad + arrow = FancyArrowPatch( + (start), (end), + connectionstyle=f"arc3,rad={arrow_rad}", + # arrowstyle=f"-|>,head_length={2*arrow_mod},head_width={arrow_mod}", + arrowstyle=f"<|-,head_length={2*arrow_mod},head_width={arrow_mod}", + linewidth=width, color=color, alpha=1, zorder=2, + shrinkA=16, shrinkB=16, mutation_scale=12, + clip_on=False + ) + ax.add_patch(arrow) + + ax.set_xlim(-spacing, (ncols - 1) * spacing + spacing) + ax.set_ylim(-3, 3) + ax.axis("off") + + plt.tight_layout() + plt.show() + plt.close(fig) + + + def save_graph(self, all_sentences, generation_sentences, path, cmap = plt.cm.Blues, wrap_width=20, thresh = 0.10, spacing = 4, arrow_mod = 1, rad = 0.3): + """ + Simplified one-row attribution graph: + - All tokens (prompts + generations) drawn in one horizontal row + - Directed weighted edges: generation -> input + """ + + grad_array = self.sentence_attr + outputs = all_sentences + generated = generation_sentences + + grad_array = grad_array.permute((1, 0)) # -> [outputs, generated] + attr_np = grad_array.cpu().numpy() if hasattr(grad_array, "cpu") else grad_array + attr_np = np.nan_to_num(attr_np, nan=0.0) + + G = nx.DiGraph() + prompt_len = len(outputs) - len(generated) + n_gen = len(generated) + + # Node ids + prompt_ids = [f"p_{i}" for i in range(prompt_len)] + gen_ids = [f"g_{j}" for j in range(n_gen)] + + # Add nodes + def add_node(node_id, label, ntype): + wrapped = textwrap.fill(label, width=wrap_width) + wrap_height = len(wrapped.split('\n')) + G.add_node(node_id, label=wrapped, type=ntype) + return wrap_height + + max_wrap_height = 0 + for i in range(prompt_len): + wrap_height = add_node(prompt_ids[i], outputs[i], "prompt") + if wrap_height > max_wrap_height: + max_wrap_height = wrap_height + for j in range(n_gen): + wrap_height = add_node(gen_ids[j], generated[j], "generated") + if wrap_height > max_wrap_height: + max_wrap_height = wrap_height + + def out_i_to_node(i): + return prompt_ids[i] if i < prompt_len else gen_ids[i - prompt_len] + + # Add edges gen -> output + for j in range(n_gen): + src = gen_ids[j] + for i in range(len(outputs)): + w = attr_np[i, j] if (i < attr_np.shape[0] and j < attr_np.shape[1]) else 0.0 + if w != 0.0: + G.add_edge(src, out_i_to_node(i), weight=w) + + + # --- layout: single row --- + y_row = 0.0 + pos = {} + all_nodes = prompt_ids + gen_ids + for idx, nid in enumerate(all_nodes): + pos[nid] = (idx * spacing, y_row) + + # --- figure --- + ncols = len(all_nodes) + fig_width = max(10, ncols * (spacing * 0.6)) + fig, ax = plt.subplots(figsize=(fig_width, 4), dpi = 300) + + # prune edges + edges = list(G.edges(data=True)) + weights = np.array([edata["weight"] for _, _, edata in edges]) + if weights.size > 0: + threshold = thresh * np.max(np.abs(weights)) # keep edges โ‰ฅ 5% of max weight + for (u, v, edata) in list(edges): # iterate over a copy + if abs(edata["weight"]) < threshold: + G.remove_edge(u, v) + + # visualization + edges = G.edges(data=True) # refresh edges after pruning + weights = np.array([edata["weight"] for _, _, edata in edges]) + if weights.size == 0: + weights = np.array([1]) # fallback if everything pruned + max_w = np.max(np.abs(weights)) + norm = mpl.colors.TwoSlopeNorm(vmin=-max_w, vcenter=0, vmax=max_w) \ + if np.min(weights) < 0 else mpl.colors.Normalize(vmin=0, vmax=max_w) + + # Draw nodes (larger font + padding) + for nid, (x, y) in pos.items(): + lbl = G.nodes[nid]["label"] + ntype = G.nodes[nid]["type"] + box_color = "#d4c1ffc8" if ntype == "prompt" else "#cfffcc" #cfe8ff + ax.annotate( + lbl, xy=(x, y), xytext=(x, y), + ha="center", va="center", fontsize=12, zorder=3, + bbox=dict(boxstyle="round,pad=0.6", facecolor=box_color, + edgecolor="gray", linewidth=1.2, alpha=1), + ) + + box_height = max_wrap_height / 4 + # Draw edges with curved arrows + for (u, v, edata) in edges: + x1, y1 = pos[u] + x2, y2 = pos[v] + + start = (x1, y1 - box_height) + end = (x2, y2 - box_height) + + w = edata["weight"] + color = cmap(norm(w)) + width = (1.5 * arrow_mod) + 5.0 * (abs(w) / max_w) + + arrow_rad = rad if x1 <= x2 else -rad + arrow = FancyArrowPatch( + (start), (end), + connectionstyle=f"arc3,rad={arrow_rad}", + # arrowstyle=f"-|>,head_length={2*arrow_mod},head_width={arrow_mod}", + arrowstyle=f"<|-,head_length={2*arrow_mod},head_width={arrow_mod}", + linewidth=width, color=color, alpha=1, zorder=2, + shrinkA=16, shrinkB=16, mutation_scale=12, + clip_on=False + ) + ax.add_patch(arrow) + + ax.set_xlim(-spacing, (ncols - 1) * spacing + spacing) + ax.set_ylim(-3, 3) + ax.axis("off") + + plt.tight_layout() + plt.savefig(path + ".png", dpi=500, transparent = "False") + fig.clear() + plt.close(fig) + + + + ########################################## recursive sentence attr ########################################## + + # this function is identical to compute_recursive_attr except for var names + # see that function for details + def compute_CAGE_sentence_attr(self, sentence_to_explain = -1, clear_values = True) -> None: + raise RuntimeError("Sentence-level CAGE has been removed; use token-level compute_CAGE_token_attr().") + + # Legacy implementation (kept for reference) + if self.sentence_attr is None: + print( + '''The sentence attribution has not been computed. + Call LLMAttributionResult.compute_sentence_attr() first. + ''' + ) + return + + if self.sentence_attr.shape[1] != len(self.all_sentences): + raise TypeError( + """This attribution object is of shape [generations, prompt]. + This function only operates on attributions of shape + [generations, prompt + generations]""" + ) + + self.CAGE_sentence_attr = self.sentence_attr[sentence_to_explain].clone() + gen_row_indices_to_collapse = list(range(0, len(self.generation_sentences[:sentence_to_explain])))[::-1] + prompt_sentences_length = len(self.prompt_sentences) + for index in gen_row_indices_to_collapse: + biased_row = self.sentence_attr[index] * self.CAGE_sentence_attr[prompt_sentences_length + index] + if clear_values: + self.CAGE_sentence_attr[prompt_sentences_length + index] = 0 + self.CAGE_sentence_attr += biased_row + + return + + + ########################################## Multi Sentence Attr ########################################## + + # this function returns a tuple containing a sentence attribution matrix, + # the sum of all rows of that matrix, the sum of indices_to_explain rows of that matrix, and a CAGE attribution over the indices_to_explain + def get_all_sentence_attrs(self, indices_to_explain) -> tuple: + raise RuntimeError("Sentence-level attribution outputs have been removed; use get_all_token_attrs([start_tok, end_tok]).") + + # Legacy implementation (kept for reference) + self.compute_sentence_attr(norm = True) + + attr = self.sentence_attr + + row_attr = 0 + for index in indices_to_explain: + row_attr += attr[index, :] + row_attr = row_attr.reshape(1, -1) + + rec_attr = 0 + for index in indices_to_explain: + self.compute_CAGE_sentence_attr(index) + rec_attr += self.CAGE_sentence_attr + rec_attr = rec_attr.reshape(1, -1) + + return attr, row_attr, rec_attr + +class LLMBasicAttribution(LLMAttribution): + def __init__(self, model, tokenizer, language: str = "en") -> None: + super().__init__(model, tokenizer) + self.zipf_language = language + + def calculate_basic_attribution(self, prompt: str, target: Optional[str] = None) -> LLMAttributionResult: + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + prompt_length = len(self.user_prompt_tokens) + generation_length = len(self.generation_tokens) + total_length = prompt_length + generation_length + + score_array = torch.zeros((generation_length, total_length), dtype=torch.float32) + + if generation_length == 0: + all_tokens = self.user_prompt_tokens + self.generation_tokens + return LLMAttributionResult( + self.tokenizer, + score_array, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=all_tokens, + ) + + if generation_length > 0 and prompt_length > 0: + normalized_prompt_tokens = [token.strip() for token in self.user_prompt_tokens] + + for gen_idx, gen_token in enumerate(self.generation_tokens): + normalized_gen_token = gen_token.strip() + + if not normalized_gen_token: + continue + + weight = float(zipf_frequency(normalized_gen_token, self.zipf_language)) + if weight <= 0.0: + continue + + for prompt_idx, prompt_token in enumerate(normalized_prompt_tokens): + if prompt_token == normalized_gen_token: + score_array[gen_idx, prompt_idx] = weight + + row_sums = score_array.sum(dim=1, keepdim=True) + nonzero_rows = row_sums.squeeze(1) > 0 + if torch.any(nonzero_rows): + score_array[nonzero_rows] = score_array[nonzero_rows] / row_sums[nonzero_rows] + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + return LLMAttributionResult( + self.tokenizer, + score_array, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=all_tokens, + ) + + +class LLMIFRAttribution(LLMAttribution): + """Information Flow Routes attribution integrated with the LLMAttribution API.""" + + def __init__( + self, + model, + tokenizer, + generate_kwargs: Optional[Dict[str, Any]] = None, + *, + chunk_tokens: int = 128, + sink_chunk_tokens: int = 32, + renorm_threshold_default: float = 0.0, + show_progress: bool = True, + recompute_attention: bool = False, + use_chat_template: bool = False, + ) -> None: + super().__init__(model, tokenizer, generate_kwargs, use_chat_template=use_chat_template) + self.chunk_tokens = int(chunk_tokens) + self.sink_chunk_tokens = int(sink_chunk_tokens) + self.renorm_threshold_default = float(renorm_threshold_default) + self.show_progress = bool(show_progress) + self.recompute_attention = bool(recompute_attention) + + @property + def _model_dtype(self) -> torch.dtype: + return next(self.model.parameters()).dtype + + def _ensure_generation(self, prompt: str, target: Optional[str]) -> Tuple[torch.Tensor, torch.Tensor, int, int]: + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + prompt_len = int(self.prompt_ids.shape[1]) + gen_len = int(self.generation_ids.shape[1]) + input_ids_all = torch.cat([self.prompt_ids, self.generation_ids], dim=1).to(self.device) + attention_mask = torch.ones_like(input_ids_all) + return input_ids_all, attention_mask, prompt_len, gen_len + + def _capture_model_state( + self, + input_ids: torch.Tensor, + attention_mask: torch.Tensor, + recompute_attention: bool = False, + ) -> Tuple[Dict[str, List[Optional[torch.Tensor]]], Optional[Sequence[torch.Tensor]], ModelMetadata, List[Dict[str, torch.Tensor | nn.Module]]]: + metadata = extract_model_metadata(self.model) + cache, hooks = attach_hooks(metadata.layers, self._model_dtype) + + try: + outputs = self.model( + input_ids=input_ids, + attention_mask=attention_mask, + use_cache=False, + output_attentions=not recompute_attention, + output_hidden_states=False, + return_dict=True, + ) + finally: + for handle in hooks: + try: + handle.remove() + except Exception: + pass + + attentions = None if recompute_attention else outputs.attentions + weight_pack = build_weight_pack(metadata, self._model_dtype) + return cache, attentions, metadata, weight_pack + + def _build_ifr_params(self, metadata: ModelMetadata, sequence_length: int) -> IFRParameters: + return IFRParameters( + n_layers=metadata.n_layers, + n_heads_q=metadata.n_heads_q, + n_kv_heads=metadata.n_kv_heads, + head_dim=metadata.head_dim, + group_size=metadata.group_size, + d_model=metadata.d_model, + sequence_length=sequence_length, + model_dtype=self._model_dtype, + chunk_tokens=self.chunk_tokens, + sink_chunk_tokens=self.sink_chunk_tokens, + ) + + def _finalize_result(self, score_array: torch.Tensor, metadata: Optional[Dict[str, Any]] = None) -> LLMAttributionResult: + if score_array.ndim == 1: + score_array = score_array.unsqueeze(0) + score_array = score_array.detach().cpu() + + score_array = self.extract_user_prompt_attributions(self.prompt_tokens, score_array) + all_tokens = self.user_prompt_tokens + self.generation_tokens + + return LLMAttributionResult( + self.tokenizer, + score_array, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=all_tokens, + metadata=metadata, + ) + + def _project_vector(self, vector: torch.Tensor) -> torch.Tensor: + matrix = vector.detach().cpu().view(1, -1) + projected = self.extract_user_prompt_attributions(self.prompt_tokens, matrix) + return projected[0] + + @torch.no_grad() + def calculate_ifr_for_all_positions( + self, + prompt: str, + target: Optional[str] = None, + *, + renorm_threshold: Optional[float] = None, + ) -> LLMAttributionResult: + input_ids_all, attn_mask, prompt_len, gen_len = self._ensure_generation(prompt, target) + total_len = int(input_ids_all.shape[1]) + if gen_len == 0: + empty = torch.zeros((0, total_len), dtype=torch.float32) + metadata = { + "ifr": { + "type": "all_positions", + "sink_indices": [], + "renorm_threshold": renorm_threshold, + "note": "No generation tokens; returning empty attribution matrix.", + } + } + return self._finalize_result(empty, metadata=metadata) + + cache, attentions, metadata, weight_pack = self._capture_model_state( + input_ids_all, attn_mask, recompute_attention=self.recompute_attention, + ) + params = self._build_ifr_params(metadata, total_len) + renorm = self.renorm_threshold_default if renorm_threshold is None else float(renorm_threshold) + + sink_range = (prompt_len, prompt_len + gen_len - 1) + all_positions = compute_ifr_for_all_positions( + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + sink_range=sink_range, + return_layerwise=False, + rotary_emb=metadata.rotary_emb, + ) + + meta = { + "ifr": { + "type": "all_positions", + "sink_indices": all_positions.sink_indices, + "renorm_threshold": renorm, + } + } + return self._finalize_result(all_positions.token_importance_matrix, metadata=meta) + + @torch.no_grad() + def calculate_ifr_for_all_positions_output_only( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_span: Optional[Tuple[int, int]] = None, + renorm_threshold: Optional[float] = None, + ) -> LLMAttributionResult: + """Compute IFR for sink positions restricted to an output span. + + This mirrors calculate_ifr_for_all_positions but only computes per-token IFR + rows for sink positions in sink_span (generation-token indices). All other + generation rows are left as NaN (becoming 0 after normalization). + """ + input_ids_all, attn_mask, prompt_len, gen_len = self._ensure_generation(prompt, target) + total_len = int(input_ids_all.shape[1]) + if gen_len == 0: + empty = torch.zeros((0, total_len), dtype=torch.float32) + metadata = { + "ifr": { + "type": "all_positions_output_only", + "sink_span_generation": None, + "sink_indices": [], + "renorm_threshold": renorm_threshold, + "note": "No generation tokens; returning empty attribution matrix.", + } + } + return self._finalize_result(empty, metadata=metadata) + + note = "" + if sink_span is None: + sink_span = (0, gen_len - 1) + note = "sink_span not provided; fell back to full generation." + span_start, span_end = sink_span + if span_start < 0 or span_end < span_start or span_end >= gen_len: + raise ValueError(f"Invalid sink_span ({span_start}, {span_end}) for generation length {gen_len}.") + + sink_start_abs = prompt_len + span_start + sink_end_abs = prompt_len + span_end + + cache, attentions, metadata, weight_pack = self._capture_model_state( + input_ids_all, attn_mask, recompute_attention=self.recompute_attention, + ) + params = self._build_ifr_params(metadata, total_len) + renorm = self.renorm_threshold_default if renorm_threshold is None else float(renorm_threshold) + + sink_range = (sink_start_abs, sink_end_abs) + all_positions = compute_ifr_for_all_positions( + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + sink_range=sink_range, + return_layerwise=False, + rotary_emb=metadata.rotary_emb, + ) + + score_array = torch.full((gen_len, total_len), torch.nan, dtype=torch.float32) + score_array[span_start : span_end + 1, :] = all_positions.token_importance_matrix + + meta = { + "ifr": { + "type": "all_positions_output_only", + "sink_span_generation": (span_start, span_end), + "sink_span_absolute": (sink_start_abs, sink_end_abs), + "sink_indices": all_positions.sink_indices, + "renorm_threshold": renorm, + "note": note, + } + } + return self._finalize_result(score_array, metadata=meta) + + @torch.no_grad() + def calculate_ifr_span( + self, + prompt: str, + target: Optional[str] = None, + *, + span: Optional[Tuple[int, int]] = None, + renorm_threshold: Optional[float] = None, + ) -> LLMAttributionResult: + input_ids_all, attn_mask, prompt_len, gen_len = self._ensure_generation(prompt, target) + total_len = int(input_ids_all.shape[1]) + + if gen_len == 0: + empty = torch.zeros((0, total_len), dtype=torch.float32) + metadata = { + "ifr": { + "type": "sentence_aggregate", + "sink_span_generation": None, + "renorm_threshold": renorm_threshold, + "note": "No generation tokens; returning empty attribution matrix.", + } + } + return self._finalize_result(empty, metadata=metadata) + + span_start, span_end = span if span is not None else (0, gen_len - 1) + if span_start < 0 or span_end < span_start or span_end >= gen_len: + raise ValueError( + f"Invalid span ({span_start}, {span_end}) for generation length {gen_len}." + ) + + sink_start_abs = prompt_len + span_start + sink_end_abs = prompt_len + span_end + + cache, attentions, metadata, weight_pack = self._capture_model_state( + input_ids_all, attn_mask, recompute_attention=self.recompute_attention, + ) + params = self._build_ifr_params(metadata, total_len) + renorm = self.renorm_threshold_default if renorm_threshold is None else float(renorm_threshold) + + aggregate = compute_ifr_sentence_aggregate( + sink_start=sink_start_abs, + sink_end=sink_end_abs, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + rotary_emb=metadata.rotary_emb, + ) + + score_array = torch.full((gen_len, total_len), torch.nan, dtype=torch.float32) + for offset in range(span_start, span_end + 1): + score_array[offset] = aggregate.token_importance_total + + meta = { + "ifr": { + "type": "sentence_aggregate", + "sink_span_generation": (span_start, span_end), + "sink_span_absolute": (sink_start_abs, sink_end_abs), + "renorm_threshold": renorm, + "aggregate": aggregate, + } + } + return self._finalize_result(score_array, metadata=meta) + + @torch.no_grad() + def calculate_ifr_multi_hop( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_span: Optional[Tuple[int, int]] = None, + thinking_span: Optional[Tuple[int, int]] = None, + n_hops: int = 1, + renorm_threshold: Optional[float] = None, + observation_mask: Optional[torch.Tensor | Sequence[float]] = None, + ) -> LLMAttributionResult: + input_ids_all, attn_mask, prompt_len, gen_len = self._ensure_generation(prompt, target) + total_len = int(input_ids_all.shape[1]) + + if gen_len == 0: + empty = torch.zeros((0, total_len), dtype=torch.float32) + metadata = { + "ifr": { + "type": "multi_hop", + "sink_span_generation": sink_span, + "thinking_span_generation": thinking_span, + "renorm_threshold": renorm_threshold, + "note": "No generation tokens; returning empty attribution matrix.", + } + } + return self._finalize_result(empty, metadata=metadata) + + if sink_span is None: + sink_span = (0, gen_len - 1) + span_start, span_end = sink_span + if span_start < 0 or span_end < span_start or span_end >= gen_len: + raise ValueError( + f"Invalid sink_span ({span_start}, {span_end}) for generation length {gen_len}." + ) + if thinking_span is None: + thinking_span = sink_span + think_start, think_end = thinking_span + if think_start < 0 or think_end < think_start or think_end >= gen_len: + raise ValueError( + f"Invalid thinking_span ({think_start}, {think_end}) for generation length {gen_len}." + ) + + sink_start_abs = prompt_len + span_start + sink_end_abs = prompt_len + span_end + think_start_abs = prompt_len + think_start + think_end_abs = prompt_len + think_end + + obs_mask_tensor: Optional[torch.Tensor] = None + if observation_mask is not None: + obs_mask_tensor = torch.as_tensor(observation_mask, dtype=torch.float32) + if obs_mask_tensor.ndim != 1: + raise ValueError("observation_mask must be a 1D tensor or sequence.") + if obs_mask_tensor.numel() == gen_len: + mask_full = torch.zeros(total_len, dtype=torch.float32) + mask_full[prompt_len : prompt_len + gen_len] = obs_mask_tensor + obs_mask_tensor = mask_full + elif obs_mask_tensor.numel() != total_len: + raise ValueError( + f"observation_mask must have length {gen_len} (generation) or {total_len} (full sequence)." + ) + + cache, attentions, metadata, weight_pack = self._capture_model_state( + input_ids_all, attn_mask, recompute_attention=self.recompute_attention, + ) + params = self._build_ifr_params(metadata, total_len) + renorm = self.renorm_threshold_default if renorm_threshold is None else float(renorm_threshold) + + multi_hop = compute_multi_hop_ifr( + sink_start=sink_start_abs, + sink_end=sink_end_abs, + thinking_span=(think_start_abs, think_end_abs), + n_hops=int(n_hops), + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + observation_mask=obs_mask_tensor, + rotary_emb=metadata.rotary_emb, + ) + + eval_vector = multi_hop.observation["sum"] + score_array = torch.full((gen_len, total_len), torch.nan, dtype=torch.float32) + for offset in range(span_start, span_end + 1): + score_array[offset] = eval_vector + + projected_per_hop = [ + self._project_vector(result.token_importance_total) for result in multi_hop.raw_attributions + ] + obs = multi_hop.observation + observation_projected = { + "mask": self.extract_user_prompt_attributions( + self.prompt_tokens, obs["mask"].view(1, -1) + )[0], + "base": self._project_vector(obs["base"]), + "sum": self._project_vector(obs["sum"]), + "avg": self._project_vector(obs["avg"]), + "per_hop": [self._project_vector(vec) for vec in obs["per_hop"]], + } + + meta: Dict[str, Any] = { + "ifr": { + "type": "multi_hop", + "sink_span_generation": (span_start, span_end), + "sink_span_absolute": (sink_start_abs, sink_end_abs), + "thinking_span_generation": (think_start, think_end), + "thinking_span_absolute": (think_start_abs, think_end_abs), + "renorm_threshold": renorm, + "n_hops": int(n_hops), + "thinking_ratios": multi_hop.thinking_ratios, + "per_hop_projected": projected_per_hop, + "observation_projected": observation_projected, + "raw": multi_hop, + } + } + + return self._finalize_result(score_array, metadata=meta) + +class LLMGradientAttribtion(LLMAttribution): + def __init__(self, model, tokenizer): + super().__init__(model, tokenizer) + + # if captum version = True, interpolation only performed over prompt tokens + # else interpolation over prompt tokens and all intermediate generations + def calculate_IG_per_generation(self, prompt, steps, baseline, batch_size = 1, captum_version = False, target = None) -> LLMAttributionResult: + # run the model so we can access the input ids and generated token ids + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + # Make a copy of the input ids + # We will expand the original prompt by each generated token + input_ids_all = self.prompt_ids.clone() + + # we want to know how many input, generated, and total tokens there are + input_length = self.prompt_ids.shape[1] + generation_length = self.generation_ids.shape[1] + total_length = input_length + generation_length + + # instantiate a matrix which will track the attribution of every generated token to the input + # cols = total_length because we will capture generation -> previous generation attributions + score_array = torch.empty((generation_length, total_length)) + + # grads must be measured to the embedding layer + embedding_layer = self.model.get_input_embeddings() + + # check batch size + batch_size = steps if steps < batch_size else batch_size + + # create alphas and set step size trapezoidal riemann sum integral estimation + alphas = torch.linspace(0, 1, steps, dtype=torch.float32).to(self.device) + step_sizes = torch.full_like((alphas), 1 / steps).to(self.device) + step_sizes[0] /= 2 + step_sizes[-1] /= 2 + + # this is used for precision casting in case the model is not loaded in fp32 + model_dtype = next(self.model.parameters()).dtype + + # we calculate the gradients of predicting self.generation_ids[step] + # by updating the input to be prompt + self.generation_ids[:step] + # for step in tqdm(range(generation_length)): + for step in range(generation_length): + # take inputs off of the graph to avoid gradient accumulation across steps + input_ids_all = input_ids_all.detach() + + # Capture the input embeddings and force require grad + input_embeds_orig = embedding_layer(input_ids_all).float() + # The baseline value is a token id. Commonly employed as 0 (for llama that is the token '!') + # also used is tokenizer.eos_token_id or tokenizer.pad_token_id + baseline_embeds = embedding_layer(torch.full_like(input_ids_all, baseline)).float() + + # set target as next known generated token + target_token = self.generation_ids[0, step].item() + + # # Make a tensor to store the gradients over all IG steps + # # each individual gradient will be [batch_size, seq_len, embedding_dim] + # IG_grads = torch.zeros((steps, input_embeds_orig.shape[1], input_embeds_orig.shape[2])).to(self.device) + + # Make a tensor to store the sum of the gradients across the IG steps + IG_sum = torch.zeros(input_embeds_orig.shape[1], input_embeds_orig.shape[2], device=self.device) + + # perform IG (gradients of interpolated inputs) + for batch_start in range(0, steps, batch_size): + # grab a batch of alphas and step sizes + batch_end = min(batch_start + batch_size, steps) + alphas_batch = alphas[batch_start : batch_end].view(-1, 1, 1).float() + step_sizes_batch = step_sizes[batch_start : batch_end].view(-1, 1, 1) + + # interpolate the batch of embeddings + # captum does not interpolate over the current generated tokens + # as a result, the generation -> generation gradients are mostly ignored + if captum_version == True: + scaled_embeds_batch = baseline_embeds[:, :input_length] + alphas_batch * (input_embeds_orig[:, :input_length] - baseline_embeds[:, :input_length]) + input_embeds_batch = input_embeds_orig.detach().clone().repeat(batch_end - batch_start, 1, 1) + input_embeds_batch[:, :input_length] = scaled_embeds_batch + # We do interpolate over the prompt and current generation + # This allows generation -> generation attributions to be captured + else: + input_embeds_batch = baseline_embeds + alphas_batch * (input_embeds_orig - baseline_embeds) # [batch_size, seq_len, embedding_dim] + + # set requires grad on input embeds + input_embeds_batch = input_embeds_batch.to(model_dtype).detach().clone().requires_grad_(True) + # perform inference + logits = self.model(inputs_embeds=input_embeds_batch).logits # [batch_size, seq_len, vocab_size] + # evaluate the probability of the target token's generation + probs = torch.nn.functional.log_softmax(logits[:, -1, :], dim=-1) # [batch_size, vocab_size] + losses = probs[:, target_token] # [batch_size] + + # clear grads + self.model.zero_grad(set_to_none=True) + if input_embeds_batch.grad is not None: + input_embeds_batch.grad.zero_() + + # gather the gradients wrt these probabilities across batch + losses.sum().backward() + + # perform (x - x') * grad * step_size + # baseline_diff = (input_embeds_orig - baseline_embeds) + # IG_grads[batch_start : batch_end] = baseline_diff * input_embeds_batch.grad.detach().clone() * step_sizes_batch # [batch_size, seq_len, embedding_dim] + + # perform (x - x') * grad * step_size + baseline_diff = (input_embeds_orig - baseline_embeds) + grads_batch = baseline_diff * input_embeds_batch.grad.detach().clone() * step_sizes_batch# [batch_size, seq_len, embedding_dim] + # Sum over batch + IG_sum += (grads_batch).sum(dim=0) # [seq_len, embedding_dim] + + # Free memory + del input_embeds_batch, logits, probs, grads_batch + torch.cuda.empty_cache() + + # del input_embeds_batch, logits, probs, losses + + # # This is a sum over the number of IG steps. Finishes IG result + # IG_grads = IG_grads.sum(0) # From [steps, seq_len, embed_dim] to [seq_len, embed_dim] + # # take the sum over the embedding_dim + # IG_grads = IG_grads.sum(-1) # [seq_len] + + # Sum across embedding dimension + IG_grads = IG_sum.sum(-1).detach().cpu() + + # pad these grads with nan since they must fit into score_array with all other token attributions + score_array[step] = self.pad_vector(IG_grads.view(1, -1), total_length, torch.nan) # [1, total_length] + + # clean up before the next loop + # del input_embeds_batch, logits, probs, losses + # torch.cuda.empty_cache() + + # Append next token to input for next step generation and attribution + input_ids_all = torch.cat([input_ids_all, torch.tensor([[target_token]]).to(self.device)], dim=1) + input_ids_all = input_ids_all.detach().clone() + + # remove from the attribution all values associated with thechat prompt + score_array = self.extract_user_prompt_attributions(self.prompt_tokens, score_array) + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + return LLMAttributionResult(self.tokenizer, score_array, self.user_prompt_tokens, self.generation_tokens, all_tokens = all_tokens) + +class LLMPerturbationAttribution(LLMAttribution): + + def __init__(self, model, tokenizer) -> None: + super().__init__(model, tokenizer) + + self.mlm_tokenizer = LongformerTokenizer.from_pretrained("allenai/longformer-base-4096") + self.mlm_model = LongformerForMaskedLM.from_pretrained("allenai/longformer-base-4096").to(self.device) + + + + # we want to evaluate the probability of producing a reponse given a prompt + def compute_logprob_response_given_prompt(self, prompt_ids, response_ids) -> torch.Tensor: + """ + Compute log-probabilities of `response_ids` given `prompt_ids`. + + prompt_ids: [B, N] + response_ids: [B, M] + Returns: [B, M] + """ + # concat prompt and response + input_ids = torch.cat([prompt_ids, response_ids], dim=1) # [B, N+M] + attention_mask = torch.ones_like(input_ids) + + # Get model outputs + logits = self.model(input_ids=input_ids, attention_mask=attention_mask).logits # [B, seq_len, vocab_size] + + # Compute log-probs + log_probs = torch.nn.functional.log_softmax(logits, dim=-1) # [B, seq_len, vocab_size] + + # Only consider response tokens + response_start = prompt_ids.shape[1] + + # Align logits to predict each y_t from y_{ torch.Tensor: + """ + Compute KL divergence scores for each token in `response_ids` given `prompt_ids`. + Mimics run_probing(metrics="kl_div") but only for the full sequence. + + Args: + model: HuggingFace autoregressive model. + prompt_ids: [B, N] tensor of prompt token IDs. + response_ids: [B, M] tensor of response token IDs. + + Returns: + KL-divergence scores: [B, M] tensor. + """ + device = prompt_ids.device + prompt_ids = prompt_ids.to(device) + response_ids = response_ids.to(device) + + # Concatenate prompt + response + input_ids = torch.cat([prompt_ids, response_ids], dim=1) # [B, N+M] + attention_mask = torch.ones_like(input_ids, device=device) + + # Compute logits + logits = self.model(input_ids=input_ids, attention_mask=attention_mask).logits # [B, N+M, V] + logits = logits.to(torch.float32) # avoid float16 overflow + log_probs = F.log_softmax(logits, dim=-1) # [B, N+M, V] + + # Align: y_t predicted from x_{ LLMAttributionResult: + # run the model so we can access the prompt ids and generated token ids + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + # Make a copy of the prompt ids + # We will expand the original prompt by each generated token + input_ids_all = self.prompt_ids.clone() + + # we want to know how many input tokens and generated tokens there are + input_length = self.prompt_ids.shape[1] + generation_length = self.generation_ids.shape[1] + total_length = input_length + generation_length + + + # given the text user prompt, create a mask over the tokens of each sentence + user_prompt_sentences = create_sentences("".join(self.user_prompt_tokens), self.tokenizer, show=True) + sentence_masks_prompt = create_sentence_masks(self.user_prompt_tokens, user_prompt_sentences, show=True) + + # mask prompt sentences and generated sentences + # given the generation, create a mask over the tokens of each sentence + generation_sentences = create_sentences("".join(self.generation_tokens), self.tokenizer) + sentence_masks_generation = create_sentence_masks(self.generation_tokens, generation_sentences) + + # find the total sizes of the masks we need + l = len(self.chat_prompt_indices) # input formating tokens + n, m = sentence_masks_prompt.shape # (user prompt sentences, user prompt tokens) + o, p = sentence_masks_generation.shape # (generation sentences + EOS, generation tokens + EOS) + + # Create a tensor that can fit all masks diagonally + masks = torch.zeros((l + n + o, l + m + p)) + + # we never mask the chat_prompt_indices, leave as 0 + # prompt indices cover: + # 0 : start of sentence_masks_prompt + # end of sentence_masks_prompt : start of sentence_masks_generation + + # input sentence masks only cover the user prompt + user_prompt_start_idx = self.user_prompt_indices[0] + masks[user_prompt_start_idx : user_prompt_start_idx + n, user_prompt_start_idx : user_prompt_start_idx + m] = sentence_masks_prompt + + # gen sentence masks only cover the generations + masks[l + n:, l + m:] = sentence_masks_generation + + num_input_masks = masks.shape[0] + + # instantiate a matrix which will track the attribution of every generated token to intermediate generations + # cols = total_length because we will capture generation -> previous generation attributions + score_array = torch.full((generation_length, total_length), torch.nan) + + for step in range(len(sentence_masks_generation)): + # for step in range(len(sentence_masks_generation) + 1): + input_ids_all = input_ids_all.detach() + + # assume the we are generating a sentence of the generation_ids and we find the + # prob of generating this sentence from the current input_ids (prompt + any current generations) + gen_token_indices = torch.where(sentence_masks_generation[step] == 1)[0] # [len(target_tokens)] + gen_tokens = self.generation_ids[:, gen_token_indices] # [1, len(target_tokens)] + + if measure == "log_loss": + original_probs = self.compute_logprob_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() # [1, len(target_tokens)] + elif measure == "KL": + original_probs = self.compute_kl_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() # [1, len(target_tokens)] + + # perturb each sentence of the input and current generation + # and measure how the probs of predicitng gen_tokens changes + for i in range(num_input_masks - len(sentence_masks_generation) + step): + # find the input tokens to be masked + tokens_to_mask = torch.where(masks[i] == 1)[0] + + # if we don't want to mask anything just continue + if len(tokens_to_mask) == 0: + continue + + # save the original token values for unmasking + original_token_value = input_ids_all[:, tokens_to_mask].clone() + # mask the values + input_ids_all[:, tokens_to_mask] = baseline + + if measure == "log_loss": + # prob of generating a token from a perturbation of the input_ids (prompt + current generations) + perturbed_probs = self.compute_logprob_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() # [1, len(target_tokens)] + elif measure == "KL": + perturbed_probs = self.compute_kl_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() # [1, len(target_tokens)] + + # change from original generation prob + score_delta = original_probs - perturbed_probs # [1, len(target_tokens)] + + # since scores are for each output token over the set of input tokens [tokens_to_mask], + # we expand them to be over all these tokens + rows, cols = torch.meshgrid(gen_token_indices, tokens_to_mask, indexing = "ij") + score_array[rows, cols] = score_delta.reshape(-1, 1).repeat((1, len(tokens_to_mask))).to(score_array.dtype) # [len(target_tokens), len(tokens_to_mask)] + + # un-ablate the input + input_ids_all[:, tokens_to_mask] = original_token_value + + # Append generated tokens to input for next step + input_ids_all = torch.cat([input_ids_all, gen_tokens], dim = 1) + + # remove from the attribution all values associated with the chat prompt + score_array = self.extract_user_prompt_attributions(self.prompt_tokens, score_array) + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + return LLMAttributionResult(self.tokenizer, score_array, self.user_prompt_tokens, self.generation_tokens, all_tokens = all_tokens) + + def mlm_mask_indices(self, input_ids, tokens_to_mask): + """ + Replace masked positions in a LLaMA token sequence using LED. + """ + + # 1. Convert input_ids to tokens + new_text_tokens = self.tokenizer.convert_ids_to_tokens(input_ids[0]) + + # 2. Mask only selected tokens + for idx in tokens_to_mask: + new_text_tokens[idx] = self.mlm_tokenizer.mask_token + + # 3. Convert tokens back to string + new_text = self.tokenizer.convert_tokens_to_string(new_text_tokens) + + # 4. Encode for Longformer MLM + inputs = self.mlm_tokenizer(new_text, return_tensors="pt", max_length=4096, truncation=True) + inputs = {k: v.to(self.device) for k, v in inputs.items()} + + # 5. Find masked positions + masked_positions = (inputs["input_ids"] == self.mlm_tokenizer.mask_token_id).nonzero(as_tuple=True)[1] + + # 6. Add global attention on masked positions + global_attention_mask = torch.zeros_like(inputs["input_ids"]) + global_attention_mask[0, masked_positions] = 1 + inputs["global_attention_mask"] = global_attention_mask + + # 7. Predict all masked positions in one forward pass + with torch.no_grad(): + logits = self.mlm_model(**inputs).logits # [batch, seq_len, vocab_size] + predicted_ids = logits[0, masked_positions, :].argmax(dim=-1) + replacement_ids = inputs["input_ids"].clone() + replacement_ids[0, masked_positions] = predicted_ids + + # 8. Convert predicted tokens to string + regenerated_tokens = [replacement_ids[0, idx] for idx in masked_positions] + regenerated_text = self.mlm_tokenizer.decode(predicted_ids, skip_special_tokens=True) + if regenerated_text and regenerated_text[0] != ' ': + regenerated_text = ' ' + regenerated_text + + # 8. Re-tokenize with LLaMA tokenizer + replacement_input_ids = self.tokenizer(regenerated_text, return_tensors='pt').input_ids + + # 9. Pad/truncate to match original masked length + original_len = len(tokens_to_mask) + new_len = replacement_input_ids.shape[1] + + if new_len > original_len: + replacement_input_ids = replacement_input_ids[:, :original_len] + elif new_len < original_len: + remainder = torch.full((1, original_len - new_len), self.tokenizer.eos_token_id, dtype=torch.long) + replacement_input_ids = torch.cat((replacement_input_ids, remainder), dim=1) + + if replacement_input_ids.dtype != torch.int64: + replacement_input_ids = replacement_input_ids.to(torch.int64) + + return replacement_input_ids.to(self.device) + + def calculate_feature_ablation_sentences_mlm(self, prompt, target = None) -> LLMAttributionResult: + # run the model so we can access the prompt ids and generated token ids + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + # Make a copy of the prompt ids + # We will expand the original prompt by each generated token + input_ids_all = self.prompt_ids.clone() + + # we want to know how many input tokens and generated tokens there are + input_length = self.prompt_ids.shape[1] + generation_length = self.generation_ids.shape[1] + total_length = input_length + generation_length + + + # given the text user prompt, create a mask over the tokens of each sentence + user_prompt_sentences = create_sentences("".join(self.user_prompt_tokens), self.tokenizer, show=True) + sentence_masks_prompt = create_sentence_masks(self.user_prompt_tokens, user_prompt_sentences, show=True) + + # mask prompt sentences and generated sentences + # given the generation, create a mask over the tokens of each sentence + generation_sentences = create_sentences("".join(self.generation_tokens), self.tokenizer) + sentence_masks_generation = create_sentence_masks(self.generation_tokens, generation_sentences) + + # find the total sizes of the masks we need + l = len(self.chat_prompt_indices) # input formating tokens + n, m = sentence_masks_prompt.shape # (user prompt sentences, user prompt tokens) + o, p = sentence_masks_generation.shape # (generation sentences + EOS, generation tokens + EOS) + + # Create a tensor that can fit all masks diagonally + masks = torch.zeros((l + n + o, l + m + p)) + + # we never mask the chat_prompt_indices, leave as 0 + # prompt indices cover: + # 0 : start of sentence_masks_prompt + # end of sentence_masks_prompt : start of sentence_masks_generation + + # input sentence masks only cover the user prompt + user_prompt_start_idx = self.user_prompt_indices[0] + masks[user_prompt_start_idx : user_prompt_start_idx + n, user_prompt_start_idx : user_prompt_start_idx + m] = sentence_masks_prompt + + # gen sentence masks only cover the generations + masks[l + n:, l + m:] = sentence_masks_generation + + num_input_masks = masks.shape[0] + + # instantiate a matrix which will track the attribution of every generated token to intermediate generations + # cols = total_length because we will capture generation -> previous generation attributions + score_array = torch.full((generation_length, total_length), torch.nan) + + for step in range(len(sentence_masks_generation)): + # for step in range(len(sentence_masks_generation) + 1): + input_ids_all = input_ids_all.detach() + + # assume the we are generating a sentence of the generation_ids and we find the + # prob of generating this sentence from the current input_ids (prompt + any current generations) + gen_token_indices = torch.where(sentence_masks_generation[step] == 1)[0] # [len(target_tokens)] + gen_tokens = self.generation_ids[:, gen_token_indices] # [1, len(target_tokens)] + + original_probs = self.compute_logprob_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() # [1, len(target_tokens)] + + # perturb each sentence of the input and current generation + # and measure how the probs of predicitng gen_tokens changes + for i in range(num_input_masks - len(sentence_masks_generation) + step): + # find the input tokens to be masked + tokens_to_mask = torch.where(masks[i] == 1)[0] + + # if we don't want to mask anything just continue + if len(tokens_to_mask) == 0: + continue + + # save the original token values for unmasking + # original_token_value = input_ids_all.clone() + original_token_value = input_ids_all[:, tokens_to_mask].clone() + + # we need replace the tokens_to_mask with roberta predicted words and turn them back into tokens + new_ids = self.mlm_mask_indices(input_ids_all, tokens_to_mask) + try: + input_ids_all[:, tokens_to_mask] = new_ids + except: + print(new_ids) + + # prob of generating a token from a perturbation of the input_ids (prompt + current generations) + perturbed_probs = self.compute_logprob_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() # [1, len(target_tokens)] + + # change from original generation prob + score_delta = original_probs - perturbed_probs # [1, len(target_tokens)] + + # since scores are for each output token over the set of input tokens [tokens_to_mask], + # we expand them to be over all these tokens + rows, cols = torch.meshgrid(gen_token_indices, tokens_to_mask, indexing = "ij") + score_array[rows, cols] = score_delta.reshape(-1, 1).repeat((1, len(tokens_to_mask))).to(score_array.dtype) # [len(target_tokens), len(tokens_to_mask)] + + # un-ablate the input + # input_ids_all = original_token_value + input_ids_all[:, tokens_to_mask] = original_token_value + + # Append generated tokens to input for next step + input_ids_all = torch.cat([input_ids_all, gen_tokens], dim = 1) + + # remove from the attribution all values associated with the chat prompt + score_array = self.extract_user_prompt_attributions(self.prompt_tokens, score_array) + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + return LLMAttributionResult(self.tokenizer, score_array, self.user_prompt_tokens, self.generation_tokens, all_tokens = all_tokens) + + +class LLMAttentionAttribution(LLMAttribution): + def __init__(self, model, tokenizer, generate_kwargs = None): + super().__init__(model, tokenizer, generate_kwargs) + + def calculate_attention_attribution(self, prompt, target = None) -> LLMAttributionResult: + # run the model so we can access the prompt ids and generated token ids + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + # Make a copy of the input ids + # We will expand the original prompt by each generated token + input_ids_all = self.prompt_ids.clone() + + # we want to know how many input and generated tokens there are + input_length = self.prompt_ids.shape[1] + generation_length = self.generation_ids.shape[1] + total_length = input_length + generation_length + + # instantiate a matrix which will track the attribution of every generated token to the input + # cols = total_length because we will capture generation -> previous generation attributions + score_array = torch.empty((generation_length, total_length)) + + with torch.no_grad(): + # for step in tqdm(range(generation_length)): + for step in range(generation_length): + input_ids_all = input_ids_all.detach() + + target_token = self.generation_ids[0, step] + + # perform inference + outputs = self.model(input_ids_all, output_attentions = True) + + # get attention weights (mean over layers, heads, and attention rows) + attentions = torch.stack(outputs.attentions, 0).mean(0).mean(1).mean(1) # [batch, seq_length] + attentions = torch.stack(outputs.attentions, 0)[-1].mean(1).mean(1) # [batch, seq_length] + # attentions = torch.stack(outputs.attentions, 0)[-1].mean(1).mean(1) # [batch, seq_length] + # pad the scores with nan since they must fit into score_array with all other token attributions + score_array[step] = self.pad_vector(attentions.detach().cpu(), total_length, torch.nan) + + # Append generated token to input for next step + input_ids_all = torch.cat([input_ids_all, torch.tensor([[target_token]]).to(self.device)], dim=1) + + # remove from the attribution all values associated with thechat prompt + score_array = self.extract_user_prompt_attributions(self.prompt_tokens, score_array) + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + return LLMAttributionResult(self.tokenizer, score_array, self.user_prompt_tokens, self.generation_tokens, all_tokens = all_tokens) + + def rollout(self, attentions): + num_blocks = attentions.shape[0] + batch_size = attentions.shape[1] + num_tokens = attentions.shape[2] + eye = torch.eye(num_tokens).expand(num_blocks, batch_size, num_tokens, num_tokens).to(attentions[0].device) + + matrices_aug = attentions + eye + + # normalize all the matrices, making residual connection addition equal to 0.5*A + 0.5*I + matrices_aug = matrices_aug / matrices_aug.sum(dim=-1, keepdim=True) + + # perform rollout + joint_attention = matrices_aug[0] + for i in range(0 + 1, num_blocks): + joint_attention = matrices_aug[i].bmm(joint_attention) + + return joint_attention + + +class LLMLRPAttribution(LLMAttribution): + """AttnLRP: Attention-Aware Layer-wise Relevance Propagation for Transformers. + + This class implements AttnLRP, a gradient-based attribution method that + leverages Layer-wise Relevance Propagation (LRP) rules adapted for + transformer architectures. + + AttnLRP achieves O(1) time complexity (single backward pass) while + providing theoretically grounded attributions with proven faithfulness. + + Reference: + AttnLRP: Attention-Aware Layer-wise Relevance Propagation for Transformers + ICML 2024. https://arxiv.org/abs/2402.05602 + + Parameters + ---------- + model : transformers model + The language model to compute attributions for + tokenizer : transformers tokenizer + The tokenizer for the model + model_type : str, optional + The model architecture type. If None, will be auto-detected. + Supported: 'qwen3', 'qwen2', 'llama' + generate_kwargs : dict, optional + Keyword arguments for model.generate() + + Example + ------- + >>> attr = LLMLRPAttribution(model, tokenizer) + >>> result = attr.calculate_attnlrp( + ... prompt="Context: Mount Everest is 8848m. Question: How high?", + ... target="8848 meters" + ... ) + >>> seq_attr, row_attr, rec_attr = result.get_all_token_attrs([0, len(result.generation_tokens) - 1]) + """ + + def __init__( + self, + model, + tokenizer, + model_type: Optional[str] = None, + generate_kwargs: Optional[Dict[str, Any]] = None, + ) -> None: + super().__init__(model, tokenizer, generate_kwargs) + + # Auto-detect or validate model type + if model_type is None: + self.model_type = detect_model_type(model) + else: + self.model_type = model_type + + def _resolve_score_mode( + self, + score_mode: Optional[Literal["max", "generated"]], + target: Optional[str], + ) -> Literal["max", "generated"]: + if score_mode is None: + return "generated" if target is not None else "max" + return score_mode + + def calculate_attnlrp( + self, + prompt: str, + target: Optional[str] = None, + *, + score_mode: Optional[Literal["max", "generated"]] = None, + ) -> LLMAttributionResult: + """Calculate AttnLRP attribution for a prompt-response pair. + + Parameters + ---------- + prompt : str + The input prompt text + target : str, optional + The target response text. If None, the model generates a response. + score_mode : Literal["max", "generated"], optional + "max": use max logit at each position (original behavior). + "generated": use the logit of the generated/target token at each position. + Default: auto ("generated" if target is provided, else "max"). + + Returns + ------- + LLMAttributionResult + Attribution result with score matrix of shape [gen_len, prompt_len + gen_len] + """ + # Get the generation (either from model or from target) + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + score_mode = self._resolve_score_mode(score_mode, target) + + # Get lengths + prompt_len = int(self.prompt_ids.shape[1]) + gen_len = int(self.generation_ids.shape[1]) + total_len = prompt_len + gen_len + + # Handle empty generation + if gen_len == 0: + empty_scores = torch.zeros((0, total_len), dtype=torch.float32) + return self._finalize_result(empty_scores) + + # Concatenate prompt and generation ids + input_ids = torch.cat([self.prompt_ids, self.generation_ids], dim=1) + + # Get the embedding layer + embedding_layer = self.model.get_input_embeddings() + + # Get model dtype for proper precision handling + model_dtype = next(self.model.parameters()).dtype + + # Initialize score array + score_array = torch.full((gen_len, total_len), torch.nan, dtype=torch.float32) + + # Apply LRP patches and compute attributions + with lrp_context(self.model, self.model_type): + # Get input embeddings with gradient tracking + input_embeds = embedding_layer(input_ids).float() + input_embeds = input_embeds.detach().clone().requires_grad_(True) + + # Forward pass with LRP-patched model + output_logits = self.model( + inputs_embeds=input_embeds.to(model_dtype), + use_cache=False, + ).logits + + # Compute attribution for each generation position + for step in range(gen_len): + gen_pos = prompt_len + step + + if score_mode == "max": + score_logit = output_logits[0, gen_pos - 1, :].max() + elif score_mode == "generated": + token_id = self.generation_ids[0, step] + score_logit = output_logits[0, gen_pos - 1, token_id] + else: + raise ValueError(f"Unsupported score_mode={score_mode}") + + # Backward pass - this computes LRP through the patched layers + if input_embeds.grad is not None: + input_embeds.grad.zero_() + + score_logit.backward(retain_graph=(step < gen_len - 1)) + + # Compute relevance: Input * Gradient, summed over embedding dimension + # Cast to float32 for numerical stability before summing + relevance = (input_embeds * input_embeds.grad).float().sum(-1).detach().cpu()[0] + + # Store in score array, padded appropriately + score_array[step, :gen_pos] = relevance[:gen_pos] + + return self._finalize_result(score_array) + + def calculate_attnlrp_batched( + self, + prompt: str, + target: Optional[str] = None, + *, + score_mode: Optional[Literal["max", "generated"]] = None, + ) -> LLMAttributionResult: + """Calculate AttnLRP attribution using batched computation. + + This is a memory-efficient version that computes attribution for + all generation positions in a single forward pass, but requires + more careful handling of gradients. + + Parameters + ---------- + prompt : str + The input prompt text + target : str, optional + The target response text. If None, the model generates a response. + score_mode : Literal["max", "generated"], optional + "max": use max logit at each position (original behavior). + "generated": use the logit of the generated/target token at each position. + Default: auto ("generated" if target is provided, else "max"). + + Returns + ------- + LLMAttributionResult + Attribution result with score matrix + """ + # Get the generation + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + score_mode = self._resolve_score_mode(score_mode, target) + + # Get lengths + prompt_len = int(self.prompt_ids.shape[1]) + gen_len = int(self.generation_ids.shape[1]) + total_len = prompt_len + gen_len + + if gen_len == 0: + empty_scores = torch.zeros((0, total_len), dtype=torch.float32) + return self._finalize_result(empty_scores) + + # Concatenate prompt and generation ids + input_ids = torch.cat([self.prompt_ids, self.generation_ids], dim=1) + + # Get embedding layer and model dtype + embedding_layer = self.model.get_input_embeddings() + model_dtype = next(self.model.parameters()).dtype + + # Initialize score array + score_array = torch.full((gen_len, total_len), torch.nan, dtype=torch.float32) + + with lrp_context(self.model, self.model_type): + # Get input embeddings + input_embeds = embedding_layer(input_ids).float() + input_embeds = input_embeds.detach().clone().requires_grad_(True) + + # Single forward pass + output_logits = self.model( + inputs_embeds=input_embeds.to(model_dtype), + use_cache=False, + ).logits + + # Get scoring logits for all generation positions + gen_positions = list(range(prompt_len - 1, prompt_len + gen_len - 1)) + if score_mode == "max": + score_logits = torch.stack([output_logits[0, pos, :].max() for pos in gen_positions]) + elif score_mode == "generated": + positions = torch.as_tensor(gen_positions, device=output_logits.device) + token_ids = self.generation_ids[0].to(device=output_logits.device) + score_logits = output_logits[0, positions, :].gather(-1, token_ids.unsqueeze(-1)).squeeze(-1) + else: + raise ValueError(f"Unsupported score_mode={score_mode}") + + # Backward from sum of all scoring logits + # This gives us the total relevance across all positions + if input_embeds.grad is not None: + input_embeds.grad.zero_() + + score_logits.sum().backward() + + # Compute aggregated relevance + relevance = (input_embeds * input_embeds.grad).float().sum(-1).detach().cpu()[0] + + # For batched version, we use the same relevance for all generation positions + # This is an approximation but much faster + for step in range(gen_len): + gen_pos = prompt_len + step + score_array[step, :gen_pos] = relevance[:gen_pos] + + return self._finalize_result(score_array) + + def _finalize_result( + self, + score_array: torch.Tensor, + metadata: Optional[Dict[str, Any]] = None, + ) -> LLMAttributionResult: + """Finalize the attribution result. + + Extracts user prompt attributions and creates the result object. + + Parameters + ---------- + score_array : torch.Tensor + Raw score array of shape [gen_len, total_len] + metadata : dict, optional + Additional metadata to include + + Returns + ------- + LLMAttributionResult + The finalized attribution result + """ + if score_array.ndim == 1: + score_array = score_array.unsqueeze(0) + score_array = score_array.detach().cpu() + + # Extract only user prompt attributions (remove chat template tokens) + score_array = self.extract_user_prompt_attributions(self.prompt_tokens, score_array) + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + if metadata is None: + metadata = {} + metadata["method"] = "attnlrp" + metadata["model_type"] = self.model_type + + return LLMAttributionResult( + self.tokenizer, + score_array, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=all_tokens, + metadata=metadata, + ) + + def calculate_attnlrp_span_aggregate( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_start: int = 0, + sink_end: Optional[int] = None, + sink_weights: Optional[torch.Tensor] = None, + normalize_weights: bool = True, + score_mode: Optional[Literal["max", "generated"]] = None, + ) -> AttnLRPSpanAggregate: + """Compute span-wise (multi-token) aggregated AttnLRP in ONE forward + ONE backward. + + This returns a single attribution vector over the whole context (prompt + generation), + equal to the weighted sum/avg of per-token AttnLRP attributions over the sink span. + + The key insight is that backward propagation is linear with respect to the objective, + and the LRP patches (divide_gradient, stop_gradient, identity_rule_implicit) are all + linear transformations on the incoming gradient. Therefore: + + R_F = x โŠ™ โˆ‚F/โˆ‚x = x โŠ™ ฮฃ_g w_g โˆ‚f_g/โˆ‚x = ฮฃ_g w_g (x โŠ™ โˆ‚f_g/โˆ‚x) = ฮฃ_g w_g R_{f_g} + + This means computing attribution for the aggregated objective F = ฮฃ w_g f_g in one + backward pass is mathematically equivalent to computing per-token attributions and + summing them with weights. + + Complexity: O(N) instead of O(Mร—N) for the naive per-token approach. + + Parameters + ---------- + prompt : str + The input prompt text + target : str, optional + The target response text. If None, the model generates a response. + sink_start : int + Start of sink span in generation token indices (inclusive). Default: 0 + sink_end : int, optional + End of sink span in generation token indices (inclusive). + Default: None (uses gen_len - 1, i.e., full generation) + sink_weights : torch.Tensor, optional + Optional tensor of shape [span_len], weighting each sink position. + Default: None (uniform weights) + normalize_weights : bool + If True, weights are normalized to sum to 1 (weighted average). + If False, computes weighted sum. Default: True + score_mode : Literal["max", "generated"], optional + "max": use max logit at each sink position (matches existing calculate_attnlrp) + "generated": use the logit of the actually generated token id at each position + Default: auto ("generated" if target is provided, else "max") + + Returns + ------- + AttnLRPSpanAggregate + Aggregated attribution result with token_importance_total vector + """ + # 1) Get generation (either from model or from target) + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + score_mode = self._resolve_score_mode(score_mode, target) + + prompt_len = int(self.prompt_ids.shape[1]) + gen_len = int(self.generation_ids.shape[1]) + total_len = prompt_len + gen_len + + # Handle empty generation + if gen_len == 0: + empty = torch.zeros((0,), dtype=torch.float32) + return AttnLRPSpanAggregate( + token_importance_total=empty, + all_tokens=[], + user_prompt_tokens=[], + generation_tokens=[], + sink_range=(0, -1), + sink_weights=None, + metadata={"method": "attnlrp_span_aggregate", "note": "empty_generation"}, + ) + + if prompt_len <= 0: + raise ValueError("prompt_len must be > 0 for causal LM attribution.") + + # Set default sink_end to full generation + if sink_end is None: + sink_end = gen_len - 1 + + sink_start = int(sink_start) + sink_end = int(sink_end) + + if not (0 <= sink_start <= sink_end < gen_len): + raise ValueError(f"Invalid sink span [{sink_start}, {sink_end}] for gen_len={gen_len}.") + + span_len = sink_end - sink_start + 1 + + # 2) Build input ids and embeddings + input_ids = torch.cat([self.prompt_ids, self.generation_ids], dim=1) + embedding_layer = self.model.get_input_embeddings() + model_dtype = next(self.model.parameters()).dtype + + # 3) Forward with LRP patches, then single backward from aggregated scalar objective + with lrp_context(self.model, self.model_type): + input_embeds = embedding_layer(input_ids).float() + input_embeds = input_embeds.detach().clone().requires_grad_(True) + + output_logits = self.model( + inputs_embeds=input_embeds.to(model_dtype), + use_cache=False, + ).logits # [1, total_len, vocab] + + device = output_logits.device + logits_dtype = output_logits.dtype + + # Positions in logits corresponding to generation indices g: + # g=0 -> pos = prompt_len - 1 (logits at position i predict token i+1) + # g=k -> pos = prompt_len + k - 1 + pos_start = prompt_len + sink_start - 1 + pos_end = prompt_len + sink_end - 1 + positions = torch.arange(pos_start, pos_end + 1, device=device) + + # Build weights tensor + if sink_weights is None: + w = torch.ones((span_len,), device=device, dtype=logits_dtype) + if normalize_weights: + w = w / float(span_len) + else: + w = sink_weights.to(device=device, dtype=logits_dtype) + if w.numel() != span_len: + raise ValueError("sink_weights length must equal (sink_end - sink_start + 1).") + if normalize_weights: + w = w / (w.sum() + 1e-12) + + # Per-position scalar targets f_g + if score_mode == "max": + # Vectorized max over vocab for each selected position + per_pos = output_logits[0, positions, :].max(dim=-1).values # [span_len] + elif score_mode == "generated": + # Logit of actually generated token id at each position + token_ids = self.generation_ids[0, sink_start:sink_end + 1].to(device=device) # [span_len] + per_pos = output_logits[0, positions, :].gather(-1, token_ids.unsqueeze(-1)).squeeze(-1) + else: + raise ValueError(f"Unsupported score_mode={score_mode}") + + # Aggregated scalar objective: F = ฮฃ w_g * f_g + objective = (w * per_pos).sum() + + if input_embeds.grad is not None: + input_embeds.grad.zero_() + + objective.backward() + + # 4) Gradient*Input relevance over embedding dim -> per-token relevance + relevance_full = (input_embeds * input_embeds.grad).float().sum(-1).detach().cpu()[0] # [total_len] + relevance_with_chat_template = relevance_full.to(torch.float32).clone() + + # 5) Strip chat template tokens (extract only user prompt + full generation tokens) + score_array = relevance_full.unsqueeze(0) # [1, total_len] + score_array = self.extract_user_prompt_attributions(self.prompt_tokens, score_array) + token_importance_total = score_array[0].to(torch.float32).cpu() + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + metadata = { + "method": "attnlrp_span_aggregate", + "base_method": "attnlrp", + "model_type": self.model_type, + "sink_range_gen": (sink_start, sink_end), + "normalize_weights": normalize_weights, + "score_mode": score_mode, + # Debug/analysis: token-level relevance aligned to the FULL tokenization + # (chat template prompt tokens + generation tokens). This does not affect + # the returned token_importance_total (which is trimmed for evaluation). + "token_importance_total_with_chat_template": relevance_with_chat_template, + "prompt_tokens_with_chat_template": list(self.prompt_tokens or []), + "user_prompt_indices": list(self.user_prompt_indices or []), + "chat_prompt_indices": list(self.chat_prompt_indices or []), + } + + return AttnLRPSpanAggregate( + token_importance_total=token_importance_total, + all_tokens=all_tokens, + user_prompt_tokens=self.user_prompt_tokens, + generation_tokens=self.generation_tokens, + sink_range=(sink_start, sink_end), + sink_weights=(sink_weights.detach().cpu() if sink_weights is not None else None), + metadata=metadata, + ) + + def calculate_attnlrp_aggregated( + self, + prompt: str, + target: Optional[str] = None, + *, + score_mode: Optional[Literal["max", "generated"]] = None, + ) -> LLMAttributionResult: + """Calculate aggregated AttnLRP attribution using span aggregation. + + This method provides an O(N) alternative to the naive O(Mร—N) per-token + AttnLRP computation. It computes attribution over the full generation span + in a single forward + backward pass. + + The resulting attribution matrix uses the same aggregated attribution + vector for all generation rows (since we're computing the combined + importance of all generation tokens at once). + + Parameters + ---------- + prompt : str + The input prompt text + target : str, optional + The target response text. If None, the model generates a response. + score_mode : Literal["max", "generated"], optional + "max": use max logit at each position (original behavior). + "generated": use the logit of the generated/target token at each position. + Default: auto ("generated" if target is provided, else "max"). + + Returns + ------- + LLMAttributionResult + Attribution result compatible with the standard evaluation pipeline + """ + # Get the generation + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + score_mode = self._resolve_score_mode(score_mode, target) + + prompt_len = int(self.prompt_ids.shape[1]) + gen_len = int(self.generation_ids.shape[1]) + total_len = prompt_len + gen_len + + # Handle empty generation + if gen_len == 0: + empty_scores = torch.zeros((0, total_len), dtype=torch.float32) + return self._finalize_result(empty_scores, metadata={ + "method": "attnlrp_aggregated", + "note": "empty_generation" + }) + + # Compute span aggregate over full generation + aggregate = self.calculate_attnlrp_span_aggregate( + prompt, + target=target, + sink_start=0, + sink_end=gen_len - 1, + normalize_weights=True, + score_mode=score_mode, + ) + + # Build score array: replicate the aggregated vector for each generation row + # We need to reconstruct the full-length vector before extraction + relevance_vector = aggregate.token_importance_total + + # The aggregate already has chat tokens stripped; we need to match the format + # expected by _finalize_result which also strips, so we create a padded version + user_prompt_len = len(self.user_prompt_tokens) + gen_token_len = len(self.generation_tokens) + expected_len = user_prompt_len + gen_token_len + + # Build score matrix + score_array = torch.full((gen_len, expected_len), torch.nan, dtype=torch.float32) + + # For each generation position, set the attribution up to that position + for step in range(gen_len): + gen_pos = user_prompt_len + step + score_array[step, :gen_pos] = relevance_vector[:gen_pos] + + metadata = { + "method": "attnlrp_aggregated", + "model_type": self.model_type, + "aggregate": aggregate, + } + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + return LLMAttributionResult( + self.tokenizer, + score_array, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=all_tokens, + metadata=metadata, + ) + + def calculate_attnlrp_ft_hop0( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_span: Optional[Tuple[int, int]] = None, + thinking_span: Optional[Tuple[int, int]] = None, + neg_handling: Literal["drop", "abs"] = "drop", + norm_mode: Literal["norm", "no_norm"] = "norm", + score_mode: Optional[Literal["max", "generated"]] = None, + ) -> LLMAttributionResult: + """Return AttnLRP hop0 from the FT multi-hop path as a token-level matrix.""" + multi_hop = self.calculate_attnlrp_multi_hop( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=0, + neg_handling=neg_handling, + norm_mode=norm_mode, + score_mode=score_mode, + ) + raw_attributions = getattr(multi_hop, "raw_attributions", None) or [] + base_attr = raw_attributions[0] if raw_attributions else None + if base_attr is None or not hasattr(base_attr, "token_importance_total"): + raise RuntimeError("AttnLRP hop0 missing from multi-hop result.") + + hop0_vec = torch.as_tensor(getattr(base_attr, "token_importance_total"), dtype=torch.float32).detach().cpu() + if hop0_vec.numel() <= 0: + raise RuntimeError("Empty generation for AttnLRP (hop0).") + + user_prompt_len = len(self.user_prompt_tokens) + gen_len = len(self.generation_tokens) + gen_len_ids = int(self.generation_ids.shape[1]) if self.generation_ids is not None else gen_len + if gen_len != gen_len_ids: + raise RuntimeError( + "AttnLRP generation length mismatch between decoded tokens and token ids: " + f"len(generation_tokens)={gen_len} vs generation_ids.shape[1]={gen_len_ids}." + ) + expected_len = user_prompt_len + gen_len + if int(hop0_vec.numel()) != expected_len: + raise RuntimeError("Unexpected AttnLRP hop0 vector length; cannot package into attribution matrix.") + + score_array = torch.full((gen_len, expected_len), torch.nan, dtype=torch.float32) + for step in range(gen_len): + gen_pos = user_prompt_len + step + score_array[step, :gen_pos] = hop0_vec[:gen_pos] + + metadata = { + "method": "attnlrp_ft_hop0", + "sink_span": tuple(getattr(base_attr, "sink_range", (0, max(0, gen_len - 1)))), + "thinking_span": thinking_span, + "n_hops": 0, + "neg_handling": neg_handling, + "norm_mode": norm_mode, + "ratio_enabled": norm_mode == "norm", + "multi_hop_result": multi_hop, + } + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + return LLMAttributionResult( + self.tokenizer, + score_array, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=all_tokens, + metadata=metadata, + ) + + def calculate_attnlrp_multi_hop( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_span: Optional[Tuple[int, int]] = None, + thinking_span: Optional[Tuple[int, int]] = None, + n_hops: int = 1, + neg_handling: Literal["drop", "abs"] = "drop", + norm_mode: Literal["norm", "no_norm"] = "norm", + score_mode: Optional[Literal["max", "generated"]] = None, + observation_mask: Optional[torch.Tensor | List[float]] = None, + ) -> MultiHopAttnLRPResult: + """Compute multi-hop AttnLRP attribution recursively through thinking span. + + This method implements recursive attribution propagation analogous to + compute_multi_hop_ifr: + + 1. Base hop (hop 0): Compute attribution from sink_span (output) to all tokens + 2. For each subsequent hop: + - Use attribution scores on thinking_span as weights + - Compute weighted attribution from thinking_span to all tokens + - Track "observation" (attribution to input tokens, excluding thinking/sink) + - Update weights for next hop + + The key insight is that attribution mass flowing through the thinking span + can be "unrolled" by recursively attributing from that span back to earlier + tokens, weighted by how much each thinking token contributed. + + Parameters + ---------- + prompt : str + The input prompt text + target : str, optional + The target response text. If None, the model generates a response. + sink_span : Tuple[int, int], optional + (start, end) indices in generation tokens for the output span. + Default: full generation (0, gen_len-1) + thinking_span : Tuple[int, int], optional + (start, end) indices in generation tokens for the reasoning span. + Default: same as sink_span + n_hops : int + Number of recursive hops. Default: 1 + neg_handling : Literal["drop", "abs"] + How to enforce non-negativity after each hop output. + "drop": clamp negative values to 0; "abs": take absolute value. + norm_mode : Literal["norm", "no_norm"] + "norm": per-hop global normalize + thinking-span normalize + enable hop ratios. + "no_norm": disable global normalize, thinking normalize, and hop ratios. + score_mode : Literal["max", "generated"], optional + "max": use max logit at each position (original behavior). + "generated": use the logit of the generated/target token at each position. + Default: auto ("generated" if target is provided, else "max"). + observation_mask : torch.Tensor or List[float], optional + Custom mask for observable tokens. Shape: (gen_len,) or (total_len,). + 1 = observable (input), 0 = not observable (thinking/output). + Default: auto-generated based on spans. + + Returns + ------- + MultiHopAttnLRPResult + Contains raw_attributions, thinking_ratios, and observation dict. + """ + # Get the generation + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + score_mode = self._resolve_score_mode(score_mode, target) + + prompt_len = int(self.prompt_ids.shape[1]) + gen_len = int(self.generation_ids.shape[1]) + total_len = prompt_len + gen_len + + # Handle empty generation + if gen_len == 0: + empty_aggregate = AttnLRPSpanAggregate( + token_importance_total=torch.zeros((0,), dtype=torch.float32), + all_tokens=[], + user_prompt_tokens=[], + generation_tokens=[], + sink_range=(0, -1), + sink_weights=None, + metadata={"method": "attnlrp_multi_hop", "note": "empty_generation"}, + ) + return MultiHopAttnLRPResult( + raw_attributions=[empty_aggregate], + thinking_ratios=[0.0], + observation={"mask": torch.tensor([]), "base": torch.tensor([]), + "per_hop": [], "sum": torch.tensor([]), "avg": torch.tensor([])}, + ) + + # Validate and set default spans + if sink_span is None: + sink_span = (0, gen_len - 1) + sink_start, sink_end = sink_span + if sink_start < 0 or sink_end < sink_start or sink_end >= gen_len: + raise ValueError(f"Invalid sink_span ({sink_start}, {sink_end}) for gen_len={gen_len}.") + + if thinking_span is None: + thinking_span = sink_span + think_start, think_end = thinking_span + if think_start < 0 or think_end < think_start or think_end >= gen_len: + raise ValueError(f"Invalid thinking_span ({think_start}, {think_end}) for gen_len={gen_len}.") + + hop_count = max(0, int(n_hops)) + ratio_enabled = norm_mode == "norm" + if neg_handling not in ("drop", "abs"): + raise ValueError("neg_handling must be 'drop' or 'abs'.") + if norm_mode not in ("norm", "no_norm"): + raise ValueError("norm_mode must be 'norm' or 'no_norm'.") + + # Compute base attribution from sink_span + base_attr = self.calculate_attnlrp_span_aggregate( + prompt, + target=target, + sink_start=sink_start, + sink_end=sink_end, + sink_weights=None, + normalize_weights=ratio_enabled, + score_mode=score_mode, + ) + + def _postprocess_hop_vector(v: torch.Tensor) -> torch.Tensor: + v = torch.nan_to_num(v.to(dtype=torch.float32), nan=0.0) + if neg_handling == "drop": + v = v.clamp(min=0.0) + else: + v = v.abs() + if ratio_enabled: + denom = float(v.sum().item()) + if denom > 0.0: + v = v / (denom + 1e-12) + else: + v = torch.zeros_like(v) + return v + + token_total = _postprocess_hop_vector(base_attr.token_importance_total) + base_attr.token_importance_total = token_total + base_attr.metadata = dict(base_attr.metadata or {}) + base_attr.metadata.update( + { + "neg_handling": neg_handling, + "norm_mode": norm_mode, + "ratio_enabled": ratio_enabled, + } + ) + + raw_attributions: List[AttnLRPSpanAggregate] = [base_attr] + + # Get the stripped token importance vector (user_prompt + generation tokens) + T = token_total.shape[0] # This is user_prompt_len + gen_len after stripping + user_prompt_len = len(self.user_prompt_tokens) + + # Build observation mask (in stripped token space) + # think_start/think_end are in generation-token indices + # In stripped space: thinking is at user_prompt_len + think_start : user_prompt_len + think_end + 1 + # sink is at user_prompt_len + sink_start : user_prompt_len + sink_end + 1 + if observation_mask is None: + obs_mask = torch.ones((T,), dtype=torch.float32) + # Mask out thinking span + think_start_stripped = user_prompt_len + think_start + think_end_stripped = user_prompt_len + think_end + obs_mask[think_start_stripped:min(think_end_stripped + 1, T)] = 0.0 + # Mask out sink span + sink_start_stripped = user_prompt_len + sink_start + sink_end_stripped = user_prompt_len + sink_end + obs_mask[sink_start_stripped:min(sink_end_stripped + 1, T)] = 0.0 + # Mask out anything after thinking span (future tokens) + if think_end_stripped + 1 < T: + obs_mask[think_end_stripped + 1:] = 0.0 + else: + obs_mask_input = torch.as_tensor(observation_mask, dtype=torch.float32) + if obs_mask_input.numel() == gen_len: + # Expand to full stripped length + obs_mask = torch.ones((T,), dtype=torch.float32) + obs_mask[user_prompt_len:user_prompt_len + gen_len] = obs_mask_input + # Keep input tokens as 1 by default + elif obs_mask_input.numel() == T: + obs_mask = obs_mask_input.clone() + else: + raise ValueError(f"observation_mask must have length {gen_len} or {T}.") + + # Compute base observation + base_obs = token_total.clone() * obs_mask + obs_accum = base_obs.clone() + per_hop_obs: List[torch.Tensor] = [] + + # Extract thinking slice weights for next hop + think_start_stripped = user_prompt_len + think_start + think_end_stripped = user_prompt_len + think_end + thinking_slice = token_total[think_start_stripped:think_end_stripped + 1].detach().clone() + if ratio_enabled: + thinking_mass = float(thinking_slice.sum().item()) + if thinking_mass > 0.0: + w_thinking = thinking_slice / (thinking_mass + 1e-12) + else: + w_thinking = torch.zeros_like(thinking_slice) + total_mass = float(token_total.sum().item()) + current_ratio = thinking_mass / (total_mass + 1e-12) if total_mass > 0 else 0.0 + ratios: List[float] = [current_ratio] + else: + w_thinking = thinking_slice + current_ratio = 1.0 + ratios = [] + + # Multi-hop iterations + for hop in range(1, hop_count + 1): + # Compute attribution from thinking span with weights from previous hop + hop_attr = self.calculate_attnlrp_span_aggregate( + prompt, + target=target, + sink_start=think_start, + sink_end=think_end, + sink_weights=w_thinking, + normalize_weights=False, + score_mode=score_mode, + ) + + hop_total = _postprocess_hop_vector(hop_attr.token_importance_total) + hop_attr.token_importance_total = hop_total + hop_attr.metadata = dict(hop_attr.metadata or {}) + hop_attr.metadata.update( + { + "neg_handling": neg_handling, + "norm_mode": norm_mode, + "ratio_enabled": ratio_enabled, + } + ) + raw_attributions.append(hop_attr) + + # Compute observation for this hop (masked and weighted by current_ratio) + obs_only = hop_total * obs_mask * (current_ratio if ratio_enabled else 1.0) + obs_accum += obs_only + per_hop_obs.append(obs_only) + + # Update weights for next hop + thinking_slice = hop_total[think_start_stripped:think_end_stripped + 1].detach().clone() + if ratio_enabled: + thinking_mass = float(thinking_slice.sum().item()) + if thinking_mass > 0.0: + w_thinking = thinking_slice / (thinking_mass + 1e-12) + else: + w_thinking = torch.zeros_like(thinking_slice) + hop_total_mass = float(hop_total.sum().item()) + if hop_total_mass <= 0.0: + current_ratio = 0.0 + else: + current_ratio *= thinking_mass / (hop_total_mass + 1e-12) + ratios.append(current_ratio) + else: + w_thinking = thinking_slice + + # Compute average observation + obs_avg = obs_accum / float(max(1, hop_count)) if hop_count > 0 else obs_accum + + observation = { + "mask": obs_mask, + "base": base_obs, + "per_hop": per_hop_obs, + "sum": obs_accum, + "avg": obs_avg, + } + + return MultiHopAttnLRPResult( + raw_attributions=raw_attributions, + thinking_ratios=ratios, + observation=observation, + ) + + def calculate_attnlrp_aggregated_multi_hop( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_span: Optional[Tuple[int, int]] = None, + thinking_span: Optional[Tuple[int, int]] = None, + n_hops: int = 1, + neg_handling: Literal["drop", "abs"] = "drop", + norm_mode: Literal["norm", "no_norm"] = "norm", + score_mode: Optional[Literal["max", "generated"]] = None, + ) -> LLMAttributionResult: + """Calculate multi-hop aggregated AttnLRP attribution. + + This is a convenience wrapper around calculate_attnlrp_multi_hop that + returns an LLMAttributionResult compatible with the evaluation pipeline. + + The returned attribution uses the observation["sum"] vector which + accumulates attribution to input tokens across all hops. + + Parameters + ---------- + prompt : str + The input prompt text + target : str, optional + The target response text. If None, the model generates a response. + sink_span : Tuple[int, int], optional + (start, end) indices in generation tokens for the output span. + thinking_span : Tuple[int, int], optional + (start, end) indices in generation tokens for the reasoning span. + n_hops : int + Number of recursive hops. Default: 1 + neg_handling : Literal["drop", "abs"] + How to enforce non-negativity after each hop output. + norm_mode : Literal["norm", "no_norm"] + "norm": per-hop global normalize + thinking-span normalize + enable hop ratios. + "no_norm": disable global normalize, thinking normalize, and hop ratios. + score_mode : Literal["max", "generated"], optional + "max": use max logit at each position (original behavior). + "generated": use the logit of the generated/target token at each position. + Default: auto ("generated" if target is provided, else "max"). + + Returns + ------- + LLMAttributionResult + Attribution result compatible with the standard evaluation pipeline + """ + # Get the generation first to set up tokens + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + gen_len = int(self.generation_ids.shape[1]) + + # Handle empty generation + if gen_len == 0: + empty_scores = torch.zeros((0, len(self.user_prompt_tokens)), dtype=torch.float32) + return LLMAttributionResult( + self.tokenizer, + empty_scores, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=self.user_prompt_tokens + self.generation_tokens, + metadata={"method": "attnlrp_aggregated_multi_hop", "note": "empty_generation"}, + ) + + # Compute multi-hop attribution + multi_hop = self.calculate_attnlrp_multi_hop( + prompt, + target=target, + sink_span=sink_span, + thinking_span=thinking_span, + n_hops=n_hops, + neg_handling=neg_handling, + norm_mode=norm_mode, + score_mode=score_mode, + ) + + # Use the accumulated observation as the relevance vector + # This gives attribution to input tokens, accumulated across hops + relevance_vector = multi_hop.observation["sum"] + + user_prompt_len = len(self.user_prompt_tokens) + gen_token_len = len(self.generation_tokens) + expected_len = user_prompt_len + gen_token_len + + # Build score matrix + score_array = torch.full((gen_len, expected_len), torch.nan, dtype=torch.float32) + + # For each generation position, set the attribution + for step in range(gen_len): + gen_pos = user_prompt_len + step + score_array[step, :gen_pos] = relevance_vector[:gen_pos] + + metadata = { + "method": "attnlrp_aggregated_multi_hop", + "model_type": self.model_type, + "n_hops": n_hops, + "sink_span": sink_span, + "thinking_span": thinking_span, + "neg_handling": neg_handling, + "norm_mode": norm_mode, + "ratio_enabled": norm_mode == "norm", + "thinking_ratios": multi_hop.thinking_ratios, + "multi_hop_result": multi_hop, + } + + all_tokens = self.user_prompt_tokens + self.generation_tokens + + return LLMAttributionResult( + self.tokenizer, + score_array, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=all_tokens, + metadata=metadata, + ) diff --git a/flashtrace/baselines/__init__.py b/flashtrace/baselines/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..9b7b42ec78321f210c7f43d73a7995d40d992b20 --- /dev/null +++ b/flashtrace/baselines/__init__.py @@ -0,0 +1,5 @@ +"""Baseline attribution methods for FlashTrace.""" + +from .attnlrp import LLMLRPAttribution + +__all__ = ["LLMLRPAttribution"] diff --git a/flashtrace/baselines/attnlrp.py b/flashtrace/baselines/attnlrp.py new file mode 100644 index 0000000000000000000000000000000000000000..b439d705f3551a658a3f0261c74b6aff9370c8cc --- /dev/null +++ b/flashtrace/baselines/attnlrp.py @@ -0,0 +1,12 @@ +"""AttnLRP baseline API.""" + +from flashtrace.attribution import AttnLRPSpanAggregate, LLMLRPAttribution, MultiHopAttnLRPResult +from flashtrace.lrp_patches import detect_model_type, lrp_context + +__all__ = [ + "AttnLRPSpanAggregate", + "LLMLRPAttribution", + "MultiHopAttnLRPResult", + "detect_model_type", + "lrp_context", +] diff --git a/flashtrace/cli.py b/flashtrace/cli.py new file mode 100644 index 0000000000000000000000000000000000000000..e0a4298f65fd9d875dc538880b67b89b75c5f093 --- /dev/null +++ b/flashtrace/cli.py @@ -0,0 +1,89 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Sequence + +from .model_io import load_model_and_tokenizer +from .tracer import FlashTrace + + +def parse_span(value: str | None) -> tuple[int, int] | None: + if value is None: + return None + parts = str(value).split(":") + if len(parts) != 2: + raise ValueError("Span must use START:END format.") + try: + start = int(parts[0]) + end = int(parts[1]) + except ValueError as exc: + raise ValueError("Span bounds must be integers.") from exc + if start < 0 or end < start: + raise ValueError("Span must satisfy 0 <= START <= END.") + return start, end + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(prog="flashtrace", description="Trace language model outputs with FlashTrace.") + sub = parser.add_subparsers(dest="command") + + trace = sub.add_parser("trace", help="Run attribution for a prompt and target.") + trace.add_argument("--model", required=True, help="Hugging Face model id or local path.") + trace.add_argument("--prompt", required=True, help="UTF-8 text file containing the prompt.") + trace.add_argument("--target", help="UTF-8 text file containing the target response.") + trace.add_argument("--output-span", help="Inclusive generation-token span START:END.") + trace.add_argument("--reasoning-span", help="Inclusive generation-token span START:END.") + trace.add_argument("--hops", type=int, default=1) + trace.add_argument("--method", default="flashtrace", choices=["flashtrace", "ifr-span", "ifr-matrix"]) + trace.add_argument("--html", help="Write standalone HTML heatmap.") + trace.add_argument("--json", help="Write JSON trace.") + trace.add_argument("--device-map", default="auto") + trace.add_argument("--dtype", default="auto", choices=["auto", "float16", "bfloat16", "float32"]) + trace.add_argument("--chunk-tokens", type=int, default=128) + trace.add_argument("--sink-chunk-tokens", type=int, default=32) + trace.add_argument("--recompute-attention", action="store_true") + trace.add_argument("--use-chat-template", action="store_true", help="Format prompts with the tokenizer chat template.") + return parser + + +def _read_text(path: str | None) -> str | None: + if path is None: + return None + return Path(path).read_text(encoding="utf-8") + + +def _run_trace(args: argparse.Namespace) -> int: + model, tokenizer = load_model_and_tokenizer(args.model, device_map=args.device_map, dtype=args.dtype) + tracer = FlashTrace( + model, + tokenizer, + chunk_tokens=args.chunk_tokens, + sink_chunk_tokens=args.sink_chunk_tokens, + recompute_attention=args.recompute_attention, + use_chat_template=args.use_chat_template, + ) + result = tracer.trace( + prompt=_read_text(args.prompt) or "", + target=_read_text(args.target), + output_span=parse_span(args.output_span), + reasoning_span=parse_span(args.reasoning_span), + hops=args.hops, + method=args.method, + ) + for item in result.topk_inputs(20): + print(f"{item.index}\t{item.score:.6f}\t{item.token!r}") + if args.json: + result.to_json(args.json) + if args.html: + result.to_html(args.html) + return 0 + + +def main(argv: Sequence[str] | None = None) -> int: + parser = build_parser() + args = parser.parse_args(argv) + if args.command == "trace": + return _run_trace(args) + parser.print_help() + return 0 diff --git a/flashtrace/core.py b/flashtrace/core.py new file mode 100644 index 0000000000000000000000000000000000000000..74c664167dde234e0558a7539313ebc9b8a7ddf5 --- /dev/null +++ b/flashtrace/core.py @@ -0,0 +1,849 @@ +"""Information Flow Routes (IFR) utilities integrated for CAGE. + +This module is adapted from the original agenttrace implementation and provides the +core tensor utilities required to compute IFR token attributions. It exposes +model-agnostic helpers that assume a Llama/Qwen style stack with the attributes +used below. The code is intentionally self-contained so it can be imported +directly by the attribution pipeline without depending on the agenttrace repo. +""" + +from __future__ import annotations + +import math +from dataclasses import dataclass +from typing import Dict, List, NamedTuple, Optional, Sequence, Tuple + +import torch +import torch.nn as nn +from torch.utils.hooks import RemovableHandle +from tqdm import tqdm + + +@dataclass +class ModelMetadata: + """Structural details extracted from the transformer decoder stack.""" + + decoder: nn.Module + layers: Sequence[nn.Module] + n_layers: int + d_model: int + n_heads_q: int + n_kv_heads: int + head_dim: int + group_size: int + rotary_emb: Optional[nn.Module] = None + + +def extract_model_metadata(model: nn.Module) -> ModelMetadata: + """Derive metadata for models with Llama/Qwen style decoder blocks.""" + + if not hasattr(model, "model"): + raise AttributeError( + "Expected a causal LM with `model` attribute exposing the decoder stack." + ) + + decoder = model.model + if not hasattr(decoder, "layers"): + raise AttributeError("Decoder does not expose `layers`; IFR assumes a layer list.") + + layers: Sequence[nn.Module] = decoder.layers + n_layers = len(layers) + if n_layers == 0: + raise ValueError("Decoder contains no layers; cannot run IFR.") + + d_model = getattr(model.config, "hidden_size", None) + if d_model is None: + raise AttributeError("Model config is missing `hidden_size`, required for IFR.") + + try: + n_heads_q = model.config.num_attention_heads + n_kv_heads = model.config.num_key_value_heads + except AttributeError: + first_attn = layers[0].self_attn + n_heads_q = getattr(first_attn, "num_heads") + n_kv_heads = getattr(first_attn, "num_key_value_groups", n_heads_q) + + group_size = n_heads_q // n_kv_heads + if n_heads_q % n_kv_heads != 0: + raise ValueError("IFR assumes grouped-query attention with integer group size.") + + head_dim = getattr(model.config, "head_dim", None) + if head_dim is None: + first_attn = layers[0].self_attn + head_dim = getattr(first_attn, "head_dim", None) + if head_dim is None: + # Fallback: infer from V projection rows. + v_rows = layers[0].self_attn.v_proj.weight.shape[0] + head_dim = v_rows // n_kv_heads + + rotary_emb = getattr(decoder, "rotary_emb", None) + if rotary_emb is None: + rotary_emb = getattr(layers[0].self_attn, "rotary_emb", None) + + return ModelMetadata( + decoder=decoder, + layers=layers, + n_layers=n_layers, + d_model=d_model, + n_heads_q=n_heads_q, + n_kv_heads=n_kv_heads, + head_dim=head_dim, + group_size=group_size, + rotary_emb=rotary_emb, + ) + + +def build_weight_pack(metadata: ModelMetadata, model_dtype: torch.dtype) -> List[Dict[str, torch.Tensor | nn.Module]]: + """Collect per-layer tensors/modules required for IFR.""" + + weight_pack: List[Dict[str, torch.Tensor | nn.Module]] = [] + for layer in metadata.layers: + attn = layer.self_attn + pack: Dict[str, torch.Tensor | nn.Module] = { + "v_w": attn.v_proj.weight.detach().to(dtype=model_dtype), + "o_w": attn.o_proj.weight.detach().to(dtype=model_dtype), + "q_w": attn.q_proj.weight.detach().to(dtype=model_dtype), + "k_w": attn.k_proj.weight.detach().to(dtype=model_dtype), + "in_ln": layer.input_layernorm, + "post_attn_ln": layer.post_attention_layernorm, + "mlp": layer.mlp, + } + q_bias = getattr(attn.q_proj, "bias", None) + k_bias = getattr(attn.k_proj, "bias", None) + if q_bias is not None: + pack["q_bias"] = q_bias.detach().to(dtype=model_dtype) + if k_bias is not None: + pack["k_bias"] = k_bias.detach().to(dtype=model_dtype) + weight_pack.append(pack) + return weight_pack + + +# --------------------------------------------------------------------------- +# Attention recomputation utilities +# --------------------------------------------------------------------------- + +def _rotate_half(x: torch.Tensor) -> torch.Tensor: + """Rotate the last dimension by half โ€” standard RoPE helper.""" + x1 = x[..., : x.shape[-1] // 2] + x2 = x[..., x.shape[-1] // 2 :] + return torch.cat((-x2, x1), dim=-1) + + +def _apply_rotary_pos_emb( + q: torch.Tensor, k: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor, +) -> Tuple[torch.Tensor, torch.Tensor]: + """Apply rotary position embeddings to Q and K tensors.""" + # cos/sin shape from HF: [1, S, head_dim] or [S, head_dim] โ€” broadcast to [1, 1, S, head_dim] + if cos.dim() == 2: + cos = cos.unsqueeze(0).unsqueeze(0) + elif cos.dim() == 3: + cos = cos.unsqueeze(1) + if sin.dim() == 2: + sin = sin.unsqueeze(0).unsqueeze(0) + elif sin.dim() == 3: + sin = sin.unsqueeze(1) + q_embed = (q * cos) + (_rotate_half(q) * sin) + k_embed = (k * cos) + (_rotate_half(k) * sin) + return q_embed, k_embed + + +@torch.no_grad() +def recompute_layer_attention( + x_prev: torch.Tensor, + layer_weights: Dict[str, torch.Tensor | nn.Module], + rotary_emb: nn.Module, + params: IFRParameters, +) -> torch.Tensor: + """Recompute attention weights for a single layer from cached activations. + + Returns attention weights of shape ``[n_heads_q, S, S]`` (post-softmax, causal masked). + This avoids the need to store all layers' attention maps simultaneously. + """ + device = x_prev.device + model_dtype = params.model_dtype + S = x_prev.shape[0] + n_heads_q = params.n_heads_q + n_kv_heads = params.n_kv_heads + head_dim = params.head_dim + group_size = params.group_size + + in_ln_mod = layer_weights["in_ln"] + q_w = layer_weights["q_w"].to(device, non_blocking=True) + k_w = layer_weights["k_w"].to(device, non_blocking=True) + + # Apply layernorm (actual, not linearized) to get the true normed input + x_normed = in_ln_mod(x_prev.unsqueeze(0)).squeeze(0).to(model_dtype) + + # Project Q and K + Q = torch.matmul(x_normed, q_w.T) # [S, n_heads_q * head_dim] + K = torch.matmul(x_normed, k_w.T) # [S, n_kv_heads * head_dim] + + q_bias = layer_weights.get("q_bias") + k_bias = layer_weights.get("k_bias") + if q_bias is not None: + Q = Q + q_bias.to(device, non_blocking=True) + if k_bias is not None: + K = K + k_bias.to(device, non_blocking=True) + + # Reshape to [1, n_heads, S, head_dim] + Q = Q.view(S, n_heads_q, head_dim).transpose(0, 1).unsqueeze(0) + K = K.view(S, n_kv_heads, head_dim).transpose(0, 1).unsqueeze(0) + + # Apply rotary position embeddings + position_ids = torch.arange(S, device=device).unsqueeze(0) + cos, sin = rotary_emb(K, position_ids) + Q, K = _apply_rotary_pos_emb(Q, K, cos, sin) + + # GQA: repeat K for grouped-query attention + K = K.repeat_interleave(group_size, dim=1) # [1, n_heads_q, S, head_dim] + + # Compute attention scores + attn_weights = torch.matmul(Q, K.transpose(2, 3)) / math.sqrt(head_dim) + + # Apply causal mask + causal_mask = torch.triu( + torch.full((S, S), float("-inf"), device=device, dtype=attn_weights.dtype), + diagonal=1, + ) + attn_weights = attn_weights + causal_mask.unsqueeze(0).unsqueeze(0) + + # Softmax + attn_weights = torch.nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32) + attn_weights = attn_weights.to(model_dtype) + + return attn_weights[0] # [n_heads_q, S, S] + + +@dataclass +class IFRParameters: + """Static configuration describing model geometry and chunk sizes.""" + + n_layers: int + n_heads_q: int + n_kv_heads: int + head_dim: int + group_size: int + d_model: int + sequence_length: int + model_dtype: torch.dtype + chunk_tokens: int + sink_chunk_tokens: int + + +@dataclass +class IFRLayerResult: + """Layer-level contributions for a single sink position.""" + + e_attn_tokens: torch.Tensor + e_resid_attn: float + head_importance: torch.Tensor + e_ffn: float + e_resid_ffn: float + + +@dataclass +class IFRAggregate: + """Aggregate IFR statistics for one or more sink positions.""" + + per_layer: List[IFRLayerResult] + token_importance_total: torch.Tensor + head_importance_total: torch.Tensor + ffn_importance_per_layer: torch.Tensor + resid_ffn_importance_per_layer: torch.Tensor + + +@dataclass +class IFRAllPositions: + """Batch of IFR outputs across a contiguous range of sink positions.""" + + token_importance_matrix: torch.Tensor + head_importance_matrix: torch.Tensor + resid_attn_fraction_total: torch.Tensor + sink_indices: List[int] + per_layer_results: Optional[List[List[IFRLayerResult]]] + note: str = "" + + +class MultiHopIFRResult(NamedTuple): + """Container returned by ``compute_multi_hop_ifr``.""" + + raw_attributions: List[IFRAggregate] + thinking_ratios: List[float] + observation: Dict[str, torch.Tensor | List[torch.Tensor]] + + +@torch.no_grad() +def attach_hooks( + layers: Sequence[nn.Module], + model_dtype: torch.dtype, +) -> Tuple[Dict[str, List[Optional[torch.Tensor]]], List[RemovableHandle]]: + """Attach forward hooks to capture residual streams and MLP activations.""" + + cache: Dict[str, List[Optional[torch.Tensor]]] = { + "pre_attn_resid": [None for _ in range(len(layers))], + "mid_resid": [None for _ in range(len(layers))], + "post_resid": [None for _ in range(len(layers))], + "mlp_out": [None for _ in range(len(layers))], + } + hooks: List[RemovableHandle] = [] + + def make_pre_ln_hook(li: int): + def hook(module: nn.Module, inputs: Tuple[torch.Tensor, ...], output: torch.Tensor) -> None: + x_in = inputs[0] + cache["pre_attn_resid"][li] = x_in.detach().to(model_dtype) + + return hook + + def make_post_attn_ln_pre_hook(li: int): + def hook(module: nn.Module, inputs: Tuple[torch.Tensor, ...]) -> None: + x_mid = inputs[0] + cache["mid_resid"][li] = x_mid.detach().to(model_dtype) + + return hook + + def make_mlp_hook(li: int): + def hook(module: nn.Module, inputs: Tuple[torch.Tensor, ...], output: torch.Tensor) -> None: + cache["mlp_out"][li] = output.detach().to(model_dtype) + + return hook + + def make_block_output_hook(li: int): + def hook(module: nn.Module, inputs: Tuple[torch.Tensor, ...], output) -> None: + x_out = output[0] if isinstance(output, (tuple, list)) else output + cache["post_resid"][li] = x_out.detach().to(model_dtype) + + return hook + + for li, layer in enumerate(layers): + hooks.append(layer.input_layernorm.register_forward_hook(make_pre_ln_hook(li))) + hooks.append( + layer.post_attention_layernorm.register_forward_pre_hook(make_post_attn_ln_pre_hook(li)) + ) + hooks.append(layer.mlp.register_forward_hook(make_mlp_hook(li))) + hooks.append(layer.register_forward_hook(make_block_output_hook(li))) + + return cache, hooks + + +def linearize_norm(module: nn.Module, x: torch.Tensor) -> torch.Tensor: + """Linearize LayerNorm/RMSNorm to obtain per-token scaling vectors.""" + + if x.dtype != torch.float32: + x = x.float() + + if hasattr(module, "weight") and module.weight is not None: + w = module.weight.detach().to(device=x.device, dtype=torch.float32).view(1, 1, -1) + else: + w = torch.ones(1, 1, x.shape[-1], dtype=torch.float32, device=x.device) + + name = module.__class__.__name__.lower() + if name.endswith("rmsnorm"): + eps = getattr(module, "eps", 1e-6) + rms = (x.pow(2).mean(dim=-1, keepdim=True) + eps).sqrt() + return w / rms + + eps = getattr(module, "eps", 1e-5) + mu = x.mean(dim=-1, keepdim=True) + sigma = ((x - mu).pow(2).mean(dim=-1, keepdim=True) + eps).sqrt() + return w / sigma + + +def l1_norm(x: torch.Tensor) -> torch.Tensor: + """Return the L1 norm reduced over the last dimension.""" + + return x.abs().sum(dim=-1) + + +def proximity(a: torch.Tensor, x: torch.Tensor) -> torch.Tensor: + """Compute proximity contributions used in IFR attribution.""" + + return torch.clamp(-l1_norm(a - x) + l1_norm(x), min=0.0) + + +@torch.no_grad() +def compute_ifr_for_position( + focus_idx: int, + cache: Dict[str, List[Optional[torch.Tensor]]], + attentions: Optional[Sequence[torch.Tensor]], + weight_pack: Sequence[Dict[str, torch.Tensor | nn.Module]], + params: IFRParameters, + renorm_threshold: float = 0.0, + rotary_emb: Optional[nn.Module] = None, +) -> IFRAggregate: + """Convenience wrapper computing IFR for a single sink position.""" + + all_ifr = compute_ifr_for_all_positions( + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm_threshold, + sink_range=(focus_idx, focus_idx), + return_layerwise=True, + rotary_emb=rotary_emb, + ) + + token_total_cpu = all_ifr.token_importance_matrix[0] + head_total_cpu = all_ifr.head_importance_matrix[0] + per_layer = all_ifr.per_layer_results[0] if all_ifr.per_layer_results is not None else [] + ffn_per_layer = torch.tensor([layer.e_ffn for layer in per_layer], dtype=torch.float32) + resid_ffn_per_layer = torch.tensor( + [layer.e_resid_ffn for layer in per_layer], dtype=torch.float32 + ) + + return IFRAggregate( + per_layer=per_layer, + token_importance_total=token_total_cpu, + head_importance_total=head_total_cpu, + ffn_importance_per_layer=ffn_per_layer, + resid_ffn_importance_per_layer=resid_ffn_per_layer, + ) + + +@torch.no_grad() +def compute_ifr_sentence_aggregate( + sink_start: int, + sink_end: int, + cache: Dict[str, List[Optional[torch.Tensor]]], + attentions: Optional[Sequence[torch.Tensor]], + weight_pack: Sequence[Dict[str, torch.Tensor | nn.Module]], + params: IFRParameters, + renorm_threshold: float = 0.0, + sink_weights: Optional[torch.Tensor] = None, + rotary_emb: Optional[nn.Module] = None, +) -> IFRAggregate: + """Aggregate IFR contributions over an inclusive sink span [sink_start, sink_end].""" + + assert 0 <= sink_start <= sink_end < params.sequence_length, "Invalid sink span." + sink_end_exclusive = sink_end + 1 + + n_layers = params.n_layers + n_heads_q = params.n_heads_q + n_kv_heads = params.n_kv_heads + group_size = params.group_size + head_dim = params.head_dim + T = params.sequence_length + model_dtype = params.model_dtype + + per_layer: List[IFRLayerResult] = [] + head_total_cpu = torch.zeros(n_heads_q, dtype=torch.float32) + token_total_cpu = torch.zeros(T, dtype=torch.float32) + ffn_per_layer = torch.zeros(n_layers, dtype=torch.float32) + resid_ffn_per_layer = torch.zeros(n_layers, dtype=torch.float32) + + J_max = sink_end_exclusive + + for li in range(n_layers): + x_prev_full = cache["pre_attn_resid"][li] + x_mid_full = cache["mid_resid"][li] + x_out_full = cache["post_resid"][li] + mlp_out_full = cache["mlp_out"][li] + + assert x_prev_full is not None + assert x_mid_full is not None + assert x_out_full is not None + assert mlp_out_full is not None + + x_prev = x_prev_full[0] + x_mid = x_mid_full[0] + x_out = x_out_full[0] + mlp_out = mlp_out_full[0] + layer_device = x_prev.device + + if x_mid.device != layer_device: + x_mid = x_mid.to(layer_device, non_blocking=True) + if x_out.device != layer_device: + x_out = x_out.to(layer_device, non_blocking=True) + if mlp_out.device != layer_device: + mlp_out = mlp_out.to(layer_device, non_blocking=True) + + if attentions is not None: + attn_li = attentions[li][0] + if attn_li.device != layer_device or attn_li.dtype != model_dtype: + attn_li = attn_li.to(device=layer_device, dtype=model_dtype, non_blocking=True) + else: + assert rotary_emb is not None, "rotary_emb is required when attentions is None" + attn_li = recompute_layer_attention(x_prev, weight_pack[li], rotary_emb, params) + + v_w = weight_pack[li]["v_w"].to(device=layer_device, non_blocking=True) + o_w = weight_pack[li]["o_w"].to(device=layer_device, non_blocking=True) + in_ln_mod = weight_pack[li]["in_ln"] + + if sink_weights is not None: + w = sink_weights.to(layer_device).to(model_dtype) + if w.numel() != (sink_end_exclusive - sink_start): + raise ValueError("sink_weights length must equal number of sink positions.") + w = w / (w.sum() + 1e-12) + w_f32 = w.to(torch.float32) + xS = ( + x_mid[sink_start:sink_end_exclusive] + .to(torch.float32) + .mul(w_f32.view(-1, 1)) + .sum(dim=0) + ) + y_resid_S = ( + x_prev[sink_start:sink_end_exclusive] + .to(torch.float32) + .mul(w_f32.view(-1, 1)) + .sum(dim=0) + ) + else: + xS = x_mid[sink_start:sink_end_exclusive].to(torch.float32).sum(dim=0) + y_resid_S = x_prev[sink_start:sink_end_exclusive].to(torch.float32).sum(dim=0) + xS_l1 = xS.abs().sum() + resid_attn_prox_S = torch.clamp(xS_l1 - (y_resid_S - xS).abs().sum(), min=0.0) + + s_prev = linearize_norm(in_ln_mod, x_prev.unsqueeze(0)).squeeze(0) + x_prev_lin = x_prev.float() * s_prev + V_all = torch.matmul(x_prev_lin.to(model_dtype), v_w.T) + V_kv = V_all.view(T, n_kv_heads, head_dim).contiguous() + V_q = V_kv.repeat_interleave(group_size, dim=1) + O_blocks = o_w.view(params.d_model, n_heads_q, head_dim).permute(1, 2, 0).contiguous() + + P = sink_end_exclusive - sink_start + alpha_slice = attn_li[:, sink_start:sink_end_exclusive, :J_max] + i_abs = torch.arange(sink_start, sink_end_exclusive, device=layer_device).view(P, 1) + j_abs = torch.arange(0, J_max, device=layer_device).view(1, J_max) + mask = (j_abs <= i_abs).to(alpha_slice.dtype) + if sink_weights is not None: + w = sink_weights.to(layer_device).to(alpha_slice.dtype) + w = w / (w.sum() + 1e-12) + alpha_weight = alpha_slice * w.view(1, -1, 1) + alpha_sum = (alpha_weight * mask.unsqueeze(0)).sum(dim=1).contiguous() + else: + alpha_sum = (alpha_slice * mask.unsqueeze(0)).sum(dim=1).contiguous() + + numer_tok_sum = torch.zeros((J_max,), device=layer_device, dtype=model_dtype) + numer_head_sum = torch.zeros((n_heads_q,), device=layer_device, dtype=model_dtype) + + for j0 in range(0, J_max, params.chunk_tokens): + j1 = min(J_max, j0 + params.chunk_tokens) + V_chunk = V_q[j0:j1] + F_chunk = torch.einsum("jhd,hdk->jhk", V_chunk, O_blocks) + A_chunk = alpha_sum[:, j0:j1].permute(1, 0).unsqueeze(-1) + W_chunk = F_chunk * A_chunk + dist = (W_chunk.float() - xS).abs().sum(dim=-1) + prox = torch.clamp(xS_l1 - dist, min=0.0) + if renorm_threshold > 0.0: + prox = prox * (prox >= renorm_threshold) + numer_tok_sum[j0:j1] += prox.sum(dim=1).to(model_dtype) + numer_head_sum += prox.sum(dim=0).to(model_dtype) + + denom_S = numer_tok_sum.float().sum() + resid_attn_prox_S + 1e-12 + e_attn_tokens_full = torch.zeros((T,), dtype=torch.float32) + e_attn_tokens_full[:J_max] = (numer_tok_sum.float() / denom_S).to(torch.float32).cpu() + e_resid_attn_S = float((resid_attn_prox_S / denom_S).item()) + head_importance_S = (numer_head_sum.float() / denom_S).to(torch.float32).cpu() + + x_out_sum = x_out[sink_start:sink_end_exclusive].to(torch.float32).sum(dim=0) + y_ffn_sum = mlp_out[sink_start:sink_end_exclusive].to(torch.float32).sum(dim=0) + x_mid_sum = x_mid[sink_start:sink_end_exclusive].to(torch.float32).sum(dim=0) + prox_ffn_S = proximity(y_ffn_sum, x_out_sum) + prox_resid_ffn_S = proximity(x_mid_sum, x_out_sum) + if renorm_threshold > 0.0: + if prox_ffn_S < renorm_threshold: + prox_ffn_S = torch.zeros((), dtype=torch.float32, device=layer_device) + if prox_resid_ffn_S < renorm_threshold: + prox_resid_ffn_S = torch.zeros((), dtype=torch.float32, device=layer_device) + denom_ffn_S = prox_ffn_S + prox_resid_ffn_S + 1e-12 + e_ffn_S = float((prox_ffn_S / denom_ffn_S).item()) + e_resid_ffn_S = float((prox_resid_ffn_S / denom_ffn_S).item()) + + per_layer.append( + IFRLayerResult( + e_attn_tokens=e_attn_tokens_full, + e_resid_attn=e_resid_attn_S, + head_importance=head_importance_S, + e_ffn=e_ffn_S, + e_resid_ffn=e_resid_ffn_S, + ) + ) + token_total_cpu += e_attn_tokens_full + head_total_cpu += head_importance_S + ffn_per_layer[li] = e_ffn_S + resid_ffn_per_layer[li] = e_resid_ffn_S + + return IFRAggregate( + per_layer=per_layer, + token_importance_total=token_total_cpu, + head_importance_total=head_total_cpu, + ffn_importance_per_layer=ffn_per_layer, + resid_ffn_importance_per_layer=resid_ffn_per_layer, + ) + + +@torch.no_grad() +def compute_multi_hop_ifr( + sink_start: int, + sink_end: int, + thinking_span: Tuple[int, int], + n_hops: int, + cache: Dict[str, List[Optional[torch.Tensor]]], + attentions: Optional[Sequence[torch.Tensor]], + weight_pack: Sequence[Dict[str, torch.Tensor | nn.Module]], + params: IFRParameters, + renorm_threshold: float = 0.0, + observation_mask: Optional[torch.Tensor] = None, + rotary_emb: Optional[nn.Module] = None, +) -> MultiHopIFRResult: + """Compute the base and multi-hop IFR distribution for a sink span.""" + + hop_count = max(0, int(n_hops)) + sink_start = int(sink_start) + sink_end = int(sink_end) + think_start = int(thinking_span[0]) + think_end = int(thinking_span[1]) + + if think_start > think_end: + raise ValueError("thinking_span start must be <= end") + + base_ifr = compute_ifr_sentence_aggregate( + sink_start=sink_start, + sink_end=sink_end, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm_threshold, + rotary_emb=rotary_emb, + ) + + raw_attributions: List[IFRAggregate] = [base_ifr] + + token_total = base_ifr.token_importance_total + T = token_total.shape[0] + if observation_mask is None: + obs_mask = torch.ones((T,), dtype=torch.float32) + obs_mask[think_start : min(think_end + 1, T)] = 0.0 + obs_mask[sink_start : min(sink_end + 1, T)] = 0.0 + if think_end + 1 < T: + obs_mask[think_end + 1 :] = 0.0 + else: + obs_mask = observation_mask.clone().to(dtype=torch.float32) + if obs_mask.shape[0] != T: + raise ValueError("observation_mask must match sequence length.") + + base_obs = token_total.clone().to(torch.float32) * obs_mask + obs_accum = base_obs.clone() + per_hop_obs: List[torch.Tensor] = [] + + thinking_slice = token_total[think_start : think_end + 1] + w_thinking = thinking_slice.detach().clone().to(params.model_dtype) + denom_base = float(token_total.sum().item()) + current_ratio = float(w_thinking.sum().item()) / (denom_base + 1e-12) if denom_base > 0 else 0.0 + ratios: List[float] = [current_ratio] + + for hop in range(1, hop_count + 1): + hop_ifr = compute_ifr_sentence_aggregate( + sink_start=think_start, + sink_end=think_end, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm_threshold, + sink_weights=w_thinking, + rotary_emb=rotary_emb, + ) + + raw_attributions.append(hop_ifr) + hop_total = hop_ifr.token_importance_total.clone().to(torch.float32) + obs_only = hop_total * obs_mask * current_ratio + obs_accum += obs_only + per_hop_obs.append(obs_only) + + thinking_slice = hop_total[think_start : think_end + 1] + w_thinking = thinking_slice.detach().clone().to(params.model_dtype) + hop_denom = float(hop_total.sum().item()) + if hop_denom <= 0.0: + current_ratio = 0.0 + else: + current_ratio *= float(w_thinking.sum().item()) / (hop_denom + 1e-12) + ratios.append(current_ratio) + + obs_avg = obs_accum / float(max(1, hop_count)) + observation = { + "mask": obs_mask, + "base": base_obs, + "per_hop": per_hop_obs, + "sum": obs_accum, + "avg": obs_avg, + } + + return MultiHopIFRResult(raw_attributions=raw_attributions, thinking_ratios=ratios, observation=observation) + + +@torch.no_grad() +def compute_ifr_for_all_positions( + cache: Dict[str, List[Optional[torch.Tensor]]], + attentions: Optional[Sequence[torch.Tensor]], + weight_pack: Sequence[Dict[str, torch.Tensor | nn.Module]], + params: IFRParameters, + renorm_threshold: float = 0.0, + sink_range: Optional[Tuple[int, int]] = None, + return_layerwise: bool = False, + rotary_emb: Optional[nn.Module] = None, +) -> IFRAllPositions: + """Compute IFR importances for every sink position in the selected range.""" + + n_layers = params.n_layers + n_heads_q = params.n_heads_q + n_kv_heads = params.n_kv_heads + group_size = params.group_size + head_dim = params.head_dim + T = params.sequence_length + model_dtype = params.model_dtype + chunk_tokens = params.chunk_tokens + sink_chunk_tokens = params.sink_chunk_tokens + + attn_start = 0 if sink_range is None else sink_range[0] + attn_end = (T - 1) if sink_range is None else sink_range[1] + assert 0 <= attn_start <= attn_end < T, "Invalid sink_range." + S = attn_end - attn_start + 1 + + token_total = torch.zeros((S, T), dtype=torch.float32) + head_total = torch.zeros((S, n_heads_q), dtype=torch.float32) + resid_attn_total = torch.zeros((S,), dtype=torch.float32) + per_layer_results: Optional[List[List[IFRLayerResult]]] = [list() for _ in range(S)] if return_layerwise else None + + for li in tqdm(range(n_layers), desc="IFR-all"): + x_prev_full = cache["pre_attn_resid"][li] + x_mid_full = cache["mid_resid"][li] + x_out_full = cache["post_resid"][li] + mlp_out_full = cache["mlp_out"][li] + + assert x_prev_full is not None + assert x_mid_full is not None + assert x_out_full is not None + assert mlp_out_full is not None + + x_prev = x_prev_full[0] + x_mid = x_mid_full[0] + x_out = x_out_full[0] + mlp_out = mlp_out_full[0] + layer_device = x_prev.device + + if x_mid.device != layer_device: + x_mid = x_mid.to(layer_device, non_blocking=True) + if x_out.device != layer_device: + x_out = x_out.to(layer_device, non_blocking=True) + if mlp_out.device != layer_device: + mlp_out = mlp_out.to(layer_device, non_blocking=True) + + if attentions is not None: + attn_li = attentions[li][0] + if attn_li.device != layer_device or attn_li.dtype != model_dtype: + attn_li = attn_li.to(device=layer_device, dtype=model_dtype, non_blocking=True) + else: + assert rotary_emb is not None, "rotary_emb is required when attentions is None" + attn_li = recompute_layer_attention(x_prev, weight_pack[li], rotary_emb, params) + + v_w = weight_pack[li]["v_w"].to(layer_device, non_blocking=True) + o_w = weight_pack[li]["o_w"].to(layer_device, non_blocking=True) + in_ln_mod = weight_pack[li]["in_ln"] + + s_prev = linearize_norm(in_ln_mod, x_prev.unsqueeze(0)).squeeze(0) + x_prev_lin = x_prev.float() * s_prev + V_all = torch.matmul(x_prev_lin.to(model_dtype), v_w.T) + V_kv = V_all.view(T, n_kv_heads, head_dim).contiguous() + V_q = V_kv.repeat_interleave(group_size, dim=1) + O_blocks = o_w.view(params.d_model, n_heads_q, head_dim).permute(1, 2, 0).contiguous() + + xA_l1_vec = x_mid.float().abs().sum(dim=-1) + resid_diff_l1_vec = (x_prev.float() - x_mid.float()).abs().sum(dim=-1) + resid_prox_vec = torch.clamp(xA_l1_vec - resid_diff_l1_vec, min=0.0) + + for i0 in range(attn_start, attn_end + 1, sink_chunk_tokens): + i1 = min(attn_end + 1, i0 + sink_chunk_tokens) + P = i1 - i0 + + numer_tok_sum = torch.zeros((P, T), device=layer_device, dtype=model_dtype) + numer_head_sum = torch.zeros((P, n_heads_q), device=layer_device, dtype=model_dtype) + + for j0 in range(0, i1, chunk_tokens): + j1 = min(i1, j0 + chunk_tokens) + V_chunk = V_q[j0:j1] + alpha_block = attn_li[:, i0:i1, j0:j1].permute(1, 2, 0).contiguous() + + i_abs = torch.arange(i0, i1, device=layer_device).view(P, 1, 1) + j_abs = torch.arange(j0, j1, device=layer_device).view(1, j1 - j0, 1) + mask = j_abs <= i_abs + + F_block = torch.einsum("jhd,hdk->jhk", V_chunk, O_blocks) + diff = alpha_block.unsqueeze(-1).float() * F_block.unsqueeze(0).float() + diff -= x_mid[i0:i1].float().unsqueeze(1).unsqueeze(2) + dist_accum = diff.abs().sum(dim=-1) + + xA_l1_chunk = xA_l1_vec[i0:i1].view(P, 1, 1) + prox = torch.clamp(xA_l1_chunk - dist_accum, min=0.0) + prox = prox * mask + if renorm_threshold > 0.0: + prox = prox * (prox >= renorm_threshold) + + numer_tok_sum[:, j0:j1] += prox.sum(dim=2).to(model_dtype) + numer_head_sum += prox.sum(dim=1).to(model_dtype) + + numer_total_i = numer_tok_sum.float().sum(dim=1) + denom = resid_prox_vec[i0:i1] + numer_total_i + 1e-12 + + e_tokens_chunk = (numer_tok_sum.float() / denom[:, None]).to(torch.float32).cpu() + e_heads_chunk = (numer_head_sum.float() / denom[:, None]).to(torch.float32).cpu() + + s0 = i0 - attn_start + s1 = i1 - attn_start + token_total[s0:s1, :] += e_tokens_chunk + head_total[s0:s1, :] += e_heads_chunk + resid_attn_total[s0:s1] += (resid_prox_vec[i0:i1] / denom).to(torch.float32).cpu() + + if return_layerwise and per_layer_results is not None: + for p in range(P): + pos_abs = i0 + p + x_out_i = x_out[pos_abs].to(torch.float32) + y_ffn_i = mlp_out[pos_abs].to(torch.float32) + x_mid_i = x_mid[pos_abs].to(torch.float32) + prox_ffn_t = proximity(y_ffn_i, x_out_i) + prox_resid_ffn_t = proximity(x_mid_i, x_out_i) + if renorm_threshold > 0.0: + if prox_ffn_t < renorm_threshold: + prox_ffn_t = torch.zeros((), dtype=torch.float32, device=layer_device) + if prox_resid_ffn_t < renorm_threshold: + prox_resid_ffn_t = torch.zeros((), dtype=torch.float32, device=layer_device) + denom_ffn_t = prox_ffn_t + prox_resid_ffn_t + 1e-12 + e_ffn = float((prox_ffn_t / denom_ffn_t).item()) + e_resid_ffn = float((prox_resid_ffn_t / denom_ffn_t).item()) + e_resid_attn = float((resid_prox_vec[pos_abs] / denom[p]).item()) + layer_result = IFRLayerResult( + e_attn_tokens=e_tokens_chunk[p], + e_resid_attn=e_resid_attn, + head_importance=e_heads_chunk[p], + e_ffn=e_ffn, + e_resid_ffn=e_resid_ffn, + ) + per_layer_results[s0 + p].append(layer_result) + + return IFRAllPositions( + token_importance_matrix=token_total, + head_importance_matrix=head_total, + resid_attn_fraction_total=resid_attn_total, + sink_indices=list(range(attn_start, attn_end + 1)), + per_layer_results=per_layer_results, + note="Sum over layers of layer-normalized importances per sink.", + ) + + +__all__ = [ + "ModelMetadata", + "extract_model_metadata", + "build_weight_pack", + "recompute_layer_attention", + "IFRParameters", + "IFRLayerResult", + "IFRAggregate", + "IFRAllPositions", + "MultiHopIFRResult", + "attach_hooks", + "compute_ifr_for_position", + "compute_ifr_sentence_aggregate", + "compute_multi_hop_ifr", + "compute_ifr_for_all_positions", +] diff --git a/flashtrace/improved.py b/flashtrace/improved.py new file mode 100644 index 0000000000000000000000000000000000000000..e8869764154b4d737b3dff576d63a347e42e9e93 --- /dev/null +++ b/flashtrace/improved.py @@ -0,0 +1,1453 @@ +from __future__ import annotations + +from dataclasses import dataclass +import math +from typing import Any, Dict, List, Optional, Sequence, Tuple + +import numpy as np +import torch + +from . import attribution as llm_attr +from .core import IFRAggregate, MultiHopIFRResult, compute_ifr_sentence_aggregate + +########################################## +# Stop-token configuration (edit here) +########################################## + +# Tokens to be treated as "stop tokens" and skipped (soft-deleted) from the full attribution flow. +# You can modify this list for different experiments. +STOP_TOKENS: List[str] = [",", "."] + +# Treat pure-whitespace tokens as stop tokens. +SKIP_WHITESPACE: bool = True + +# Match stop tokens after stripping leading/trailing whitespace. +STRIP_BEFORE_MATCH: bool = True + + +def is_stop_token(token: str) -> bool: + if token is None: + return False + t = str(token) + if STRIP_BEFORE_MATCH: + t = t.strip() + if SKIP_WHITESPACE and t == "": + return True + return t in STOP_TOKENS + + +def keep_token_indices(tokens: Sequence[str]) -> List[int]: + return [i for i, tok in enumerate(tokens) if not is_stop_token(tok)] + + +def _last_attributable_generation_index( + tokenizer: Any, + generation_ids: torch.Tensor, + generation_tokens: Sequence[str], +) -> int: + end = int(generation_ids.shape[1]) - 1 + if end < 0: + return -1 + + last_id = int(generation_ids[0, end].item()) + eos_token_id = getattr(tokenizer, "eos_token_id", None) + if eos_token_id is not None: + eos_ids = eos_token_id if isinstance(eos_token_id, (list, tuple, set)) else [eos_token_id] + if any(last_id == int(eos_id) for eos_id in eos_ids if eos_id is not None): + return end - 1 + + if end < len(generation_tokens) and is_stop_token(generation_tokens[end]): + return end - 1 + + return end + + +def _stop_keep_mask(tokens: Sequence[str]) -> torch.Tensor: + keep = [0.0 if is_stop_token(tok) else 1.0 for tok in tokens] + return torch.as_tensor(keep, dtype=torch.float32) + + +def _build_stop_keep_mask_full( + *, + prompt_len_full: int, + gen_len: int, + user_prompt_indices: Sequence[int], + user_prompt_tokens: Sequence[str], + generation_tokens: Sequence[str], +) -> torch.Tensor: + """Return a float32 mask over the full sequence (chat template + user prompt + generation).""" + total_len = int(prompt_len_full) + int(gen_len) + mask = torch.ones((total_len,), dtype=torch.float32) + + prompt_keep = _stop_keep_mask(user_prompt_tokens) + for j, abs_idx in enumerate(user_prompt_indices): + if 0 <= int(abs_idx) < int(prompt_len_full) and j < int(prompt_keep.numel()): + mask[int(abs_idx)] = prompt_keep[j] + + gen_keep = _stop_keep_mask(generation_tokens) + for g in range(int(gen_keep.numel())): + abs_idx = int(prompt_len_full) + g + if 0 <= abs_idx < total_len: + mask[abs_idx] = gen_keep[g] + + return mask + + +def faithfulness_test_skip_tokens( + llm_evaluator: Any, + attribution: torch.Tensor, + prompt: str, + generation: str, + *, + keep_prompt_token_indices: Sequence[int], + user_prompt_indices: Optional[Sequence[int]] = None, + k: int = 20, +) -> Tuple[float, float, float]: + """Token-level MAS/RISE faithfulness via guided deletion in k perturbation steps, skipping specified prompt tokens. + + This is a drop-in replacement for llm_attr_eval.LLMAttributionEvaluator.faithfulness_test + when an experimental protocol wants to soft-delete some prompt tokens (e.g., stop tokens) + from the perturbation path. + """ + + def auc(arr: np.ndarray) -> float: + return (arr.sum() - arr[0] / 2 - arr[-1] / 2) / max(1, (arr.shape[0] - 1)) + + pad_token_id = llm_evaluator._ensure_pad_token_id() + + user_prompt = " " + prompt + formatted_prompt = llm_evaluator.format_prompt(user_prompt) + + formatted_ids = llm_evaluator.tokenizer(formatted_prompt, return_tensors="pt", add_special_tokens=False).input_ids + prompt_ids = formatted_ids.to(llm_evaluator.device) + prompt_ids_perturbed = prompt_ids.clone() + + generation_ids = llm_evaluator.tokenizer( + generation + llm_evaluator.tokenizer.eos_token, + return_tensors="pt", + add_special_tokens=False, + ).input_ids.to(llm_evaluator.device) + + attr_cpu = attribution.detach().cpu() + w = attr_cpu.sum(0) + P = int(w.numel()) + + keep: List[int] = [] + seen: set[int] = set() + for raw in keep_prompt_token_indices: + try: + idx = int(raw) + except Exception: + continue + if 0 <= idx < P and idx not in seen: + keep.append(idx) + seen.add(idx) + keep.sort() + + K = len(keep) + if K > 0: + steps = int(k) if k is not None else 0 + if steps <= 0: + steps = 1 + steps = min(steps, K) + else: + steps = 0 + + scores = np.zeros(steps + 1, dtype=np.float64) + density = np.zeros(steps + 1, dtype=np.float64) + + if user_prompt_indices is not None: + prompt_positions = [int(x) for x in user_prompt_indices] + if len(prompt_positions) != P: + raise ValueError( + "user_prompt_indices length does not match prompt-side attribution length: " + f"indices P={len(prompt_positions)}, attr P={P}." + ) + if P and max(prompt_positions) >= int(prompt_ids_perturbed.shape[1]): + raise ValueError("user_prompt_indices contains an out-of-bounds index for formatted prompt ids.") + else: + user_ids = llm_evaluator.tokenizer(user_prompt, return_tensors="pt", add_special_tokens=False).input_ids + user_start = llm_evaluator._find_subsequence_start(formatted_ids[0], user_ids[0]) + if user_start is None: + raise RuntimeError("Failed to locate user prompt token span inside formatted chat prompt.") + prompt_positions = [int(user_start) + j for j in range(P)] + + scores[0] = ( + llm_evaluator.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + ) + density[0] = 1.0 + + if K == 0: + return auc(scores), auc(scores), auc(scores) + + w_keep = w.index_select(0, torch.as_tensor(keep, dtype=torch.long)) + sorted_local = torch.argsort(w_keep, descending=True) + sorted_keep = [keep[int(i.item())] for i in sorted_local] + attr_sum = float(w_keep.sum().item()) + + if attr_sum <= 0: + density = np.linspace(1.0, 0.0, steps + 1) + + base = K // steps + remainder = K % steps + start = 0 + for step in range(steps): + size = base + (1 if step < remainder else 0) + group = sorted_keep[start : start + size] + start += size + + for idx in group: + abs_pos = int(prompt_positions[int(idx)]) + prompt_ids_perturbed[0, abs_pos] = pad_token_id + scores[step + 1] = ( + llm_evaluator.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + ) + if attr_sum > 0: + dec = float(w.index_select(0, torch.as_tensor(group, dtype=torch.long)).sum().item()) / attr_sum + density[step + 1] = density[step] - dec + + min_normalized_pred = 1.0 + normalized_model_response = scores.copy() + for i in range(len(scores)): + normalized_pred = (normalized_model_response[i] - scores[-1]) / (abs(scores[0] - scores[-1])) + normalized_pred = np.clip(normalized_pred, 0.0, 1.0) + min_normalized_pred = min(min_normalized_pred, normalized_pred) + normalized_model_response[i] = min_normalized_pred + + alignment_penalty = np.abs(normalized_model_response - density) + corrected_scores = normalized_model_response + alignment_penalty + corrected_scores = corrected_scores.clip(0.0, 1.0) + corrected_scores = (corrected_scores - np.min(corrected_scores)) / (np.max(corrected_scores) - np.min(corrected_scores)) + + if np.isnan(corrected_scores).any(): + corrected_scores = np.linspace(1.0, 0.0, len(scores)) + + return auc(normalized_model_response), auc(corrected_scores), auc(normalized_model_response + alignment_penalty) + + +def evaluate_attr_recovery_skip_tokens( + attribution_prompt: torch.Tensor, + *, + keep_prompt_token_indices: Sequence[int], + gold_prompt_token_indices: Sequence[int], + top_fraction: float = 0.1, +) -> float: + """Recall of gold prompt tokens among top-attributed prompt tokens, skipping specified tokens.""" + if attribution_prompt.ndim != 2: + raise ValueError("Expected 2D prompt-side attribution matrix [R, P].") + + P = int(attribution_prompt.shape[1]) + keep: List[int] = [] + seen: set[int] = set() + for raw in keep_prompt_token_indices or []: + try: + idx = int(raw) + except Exception: + continue + if 0 <= idx < P and idx not in seen: + keep.append(idx) + seen.add(idx) + keep.sort() + if not keep: + return float("nan") + + gold: set[int] = set() + for raw in gold_prompt_token_indices or []: + try: + idx = int(raw) + except Exception: + continue + if idx in seen: + gold.add(idx) + if not gold: + return float("nan") + + w = torch.nan_to_num(attribution_prompt.sum(0).to(dtype=torch.float32), nan=0.0).clamp(min=0.0) + w_keep = w.index_select(0, torch.as_tensor(keep, dtype=torch.long)) + + frac = float(top_fraction) + if frac < 0.0: + frac = 0.0 + if frac > 1.0: + frac = 1.0 + k = max(1, int(math.ceil(float(len(keep)) * frac))) + k = min(k, int(len(keep))) + topk_local = torch.topk(w_keep, k, largest=True).indices.tolist() + topk = {keep[int(i)] for i in topk_local} + hit = len(topk.intersection(gold)) + return float(hit) / float(len(gold)) + + +@dataclass +class StopTokenConfig: + stop_tokens: List[str] + skip_whitespace: bool + strip_before_match: bool + + +class LLMIFRAttributionImproved(llm_attr.LLMIFRAttribution): + """Experimental FT-IFR (ifr_multi_hop_stop_words) variant with stop-token soft deletion.""" + + def _stop_config(self) -> StopTokenConfig: + return StopTokenConfig( + stop_tokens=list(STOP_TOKENS), + skip_whitespace=bool(SKIP_WHITESPACE), + strip_before_match=bool(STRIP_BEFORE_MATCH), + ) + + @torch.no_grad() + def calculate_ifr_multi_hop_stop_words( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_span: Optional[Tuple[int, int]] = None, + thinking_span: Optional[Tuple[int, int]] = None, + n_hops: int = 1, + renorm_threshold: Optional[float] = None, + observation_mask: Optional[torch.Tensor | Sequence[float]] = None, + ) -> llm_attr.LLMAttributionResult: + input_ids_all, attn_mask, prompt_len_full, gen_len = self._ensure_generation(prompt, target) + total_len = int(input_ids_all.shape[1]) + + if gen_len == 0: + empty = torch.zeros((0, total_len), dtype=torch.float32) + metadata = { + "ifr": { + "type": "multi_hop_stop_words", + "sink_span_generation": sink_span, + "thinking_span_generation": thinking_span, + "renorm_threshold": renorm_threshold, + "stop_config": self._stop_config().__dict__, + "note": "No generation tokens; returning empty attribution matrix.", + } + } + return self._finalize_result(empty, metadata=metadata) + + if sink_span is None: + sink_span = (0, gen_len - 1) + span_start, span_end = sink_span + if span_start < 0 or span_end < span_start or span_end >= gen_len: + raise ValueError(f"Invalid sink_span ({span_start}, {span_end}) for generation length {gen_len}.") + + if thinking_span is None: + thinking_span = sink_span + think_start, think_end = thinking_span + if think_start < 0 or think_end < think_start or think_end >= gen_len: + raise ValueError(f"Invalid thinking_span ({think_start}, {think_end}) for generation length {gen_len}.") + + sink_start_abs = int(prompt_len_full) + int(span_start) + sink_end_abs = int(prompt_len_full) + int(span_end) + think_start_abs = int(prompt_len_full) + int(think_start) + think_end_abs = int(prompt_len_full) + int(think_end) + + obs_mask_tensor: Optional[torch.Tensor] = None + if observation_mask is not None: + obs_mask_tensor = torch.as_tensor(observation_mask, dtype=torch.float32) + if obs_mask_tensor.ndim != 1: + raise ValueError("observation_mask must be a 1D tensor or sequence.") + if obs_mask_tensor.numel() == gen_len: + mask_full = torch.zeros(total_len, dtype=torch.float32) + mask_full[int(prompt_len_full) : int(prompt_len_full) + int(gen_len)] = obs_mask_tensor + obs_mask_tensor = mask_full + elif obs_mask_tensor.numel() != total_len: + raise ValueError( + f"observation_mask must have length {gen_len} (generation) or {total_len} (full sequence)." + ) + + stop_keep_mask_full = _build_stop_keep_mask_full( + prompt_len_full=int(prompt_len_full), + gen_len=int(gen_len), + user_prompt_indices=list(getattr(self, "user_prompt_indices", []) or []), + user_prompt_tokens=list(getattr(self, "user_prompt_tokens", []) or []), + generation_tokens=list(getattr(self, "generation_tokens", []) or []), + ) + + cache, attentions, metadata, weight_pack = self._capture_model_state( + input_ids_all, attn_mask, recompute_attention=self.recompute_attention, + ) + params = self._build_ifr_params(metadata, total_len) + renorm = self.renorm_threshold_default if renorm_threshold is None else float(renorm_threshold) + + hop_count = max(0, int(n_hops)) + + # Base: sink-span aggregate, with sink positions masked if they are stop tokens. + sink_gen_tokens = list(getattr(self, "generation_tokens", []) or []) + sink_stops = [] + for gi in range(int(span_start), int(span_end) + 1): + tok = sink_gen_tokens[gi] if 0 <= gi < len(sink_gen_tokens) else "" + sink_stops.append(is_stop_token(tok)) + base_weights = None + if any(sink_stops): + base_weights = torch.as_tensor( + [0.0 if st else 1.0 for st in sink_stops], + dtype=params.model_dtype, + ) + + base_ifr_raw = compute_ifr_sentence_aggregate( + sink_start=sink_start_abs, + sink_end=sink_end_abs, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + sink_weights=base_weights, + rotary_emb=metadata.rotary_emb, + ) + + base_total = base_ifr_raw.token_importance_total.to(dtype=torch.float32) * stop_keep_mask_full + base_ifr = IFRAggregate( + per_layer=base_ifr_raw.per_layer, + token_importance_total=base_total, + head_importance_total=base_ifr_raw.head_importance_total, + ffn_importance_per_layer=base_ifr_raw.ffn_importance_per_layer, + resid_ffn_importance_per_layer=base_ifr_raw.resid_ffn_importance_per_layer, + ) + + raw_attributions: List[IFRAggregate] = [base_ifr] + + # Observation mask: respect provided observation_mask, otherwise follow the core FT behavior, + # and then apply stop-token masking so stop tokens are fully removed from the observation path. + if obs_mask_tensor is None: + obs_mask = torch.ones((total_len,), dtype=torch.float32) + obs_mask[int(think_start_abs) : min(int(think_end_abs) + 1, total_len)] = 0.0 + obs_mask[int(sink_start_abs) : min(int(sink_end_abs) + 1, total_len)] = 0.0 + if int(think_end_abs) + 1 < total_len: + obs_mask[int(think_end_abs) + 1 :] = 0.0 + else: + obs_mask = obs_mask_tensor.clone().to(dtype=torch.float32) + if int(obs_mask.shape[0]) != int(total_len): + raise ValueError("observation_mask must match sequence length.") + + obs_mask = obs_mask * stop_keep_mask_full + + base_obs = base_total.clone() * obs_mask + obs_accum = base_obs.clone() + per_hop_obs: List[torch.Tensor] = [] + + denom_base = float(base_total.sum().item()) + thinking_slice = base_total[int(think_start_abs) : int(think_end_abs) + 1] + w_thinking = thinking_slice.detach().clone().to(params.model_dtype) + current_ratio = float(w_thinking.sum().item()) / (denom_base + 1e-12) if denom_base > 0 else 0.0 + ratios: List[float] = [current_ratio] + + # Multi-hop: thinking-span re-aggregation with masked weights. + for hop in range(1, hop_count + 1): + if float(w_thinking.sum().item()) <= 0.0 or float(current_ratio) <= 0.0: + # Terminate remaining hops with zero vectors to keep shapes stable. + zeros = torch.zeros_like(base_total) + for _ in range(hop, hop_count + 1): + raw_attributions.append( + IFRAggregate( + per_layer=[], + token_importance_total=zeros, + head_importance_total=torch.zeros_like(base_ifr.head_importance_total), + ffn_importance_per_layer=torch.zeros_like(base_ifr.ffn_importance_per_layer), + resid_ffn_importance_per_layer=torch.zeros_like(base_ifr.resid_ffn_importance_per_layer), + ) + ) + per_hop_obs.append(torch.zeros_like(base_total)) + ratios.append(0.0) + break + + hop_ifr_raw = compute_ifr_sentence_aggregate( + sink_start=think_start_abs, + sink_end=think_end_abs, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + sink_weights=w_thinking, + rotary_emb=metadata.rotary_emb, + ) + + hop_total = hop_ifr_raw.token_importance_total.to(dtype=torch.float32) * stop_keep_mask_full + hop_ifr = IFRAggregate( + per_layer=hop_ifr_raw.per_layer, + token_importance_total=hop_total, + head_importance_total=hop_ifr_raw.head_importance_total, + ffn_importance_per_layer=hop_ifr_raw.ffn_importance_per_layer, + resid_ffn_importance_per_layer=hop_ifr_raw.resid_ffn_importance_per_layer, + ) + raw_attributions.append(hop_ifr) + + obs_only = hop_total * obs_mask * float(current_ratio) + obs_accum += obs_only + per_hop_obs.append(obs_only) + + thinking_slice = hop_total[int(think_start_abs) : int(think_end_abs) + 1] + w_thinking = thinking_slice.detach().clone().to(params.model_dtype) + + hop_denom = float(hop_total.sum().item()) + if hop_denom <= 0.0: + current_ratio = 0.0 + else: + current_ratio *= float(w_thinking.sum().item()) / (hop_denom + 1e-12) + ratios.append(float(current_ratio)) + + obs_avg = obs_accum / float(max(1, hop_count)) + observation: Dict[str, torch.Tensor | List[torch.Tensor]] = { + "mask": obs_mask, + "base": base_obs, + "per_hop": per_hop_obs, + "sum": obs_accum, + "avg": obs_avg, + } + + multi_hop = MultiHopIFRResult(raw_attributions=raw_attributions, thinking_ratios=ratios, observation=observation) + + eval_vector = multi_hop.observation["sum"] + score_array = torch.full((gen_len, total_len), torch.nan, dtype=torch.float32) + for offset in range(int(span_start), int(span_end) + 1): + tok = sink_gen_tokens[offset] if 0 <= offset < len(sink_gen_tokens) else "" + if is_stop_token(tok): + continue + score_array[offset] = eval_vector + + projected_per_hop = [self._project_vector(result.token_importance_total) for result in multi_hop.raw_attributions] + obs = multi_hop.observation + observation_projected = { + "mask": self.extract_user_prompt_attributions(self.prompt_tokens, obs["mask"].view(1, -1))[0], + "base": self._project_vector(obs["base"]), + "sum": self._project_vector(obs["sum"]), + "avg": self._project_vector(obs["avg"]), + "per_hop": [self._project_vector(vec) for vec in obs["per_hop"]], + } + + meta: Dict[str, Any] = { + "ifr": { + "type": "multi_hop_stop_words", + "sink_span_generation": (int(span_start), int(span_end)), + "sink_span_absolute": (int(sink_start_abs), int(sink_end_abs)), + "thinking_span_generation": (int(think_start), int(think_end)), + "thinking_span_absolute": (int(think_start_abs), int(think_end_abs)), + "renorm_threshold": float(renorm), + "n_hops": int(n_hops), + "thinking_ratios": ratios, + "per_hop_projected": projected_per_hop, + "observation_projected": observation_projected, + "stop_config": self._stop_config().__dict__, + "raw": multi_hop, + } + } + + return self._finalize_result(score_array, metadata=meta) + + +########################################## +# Split-hop configuration (edit here) +########################################## + +# Default number of equal-length segments to split the thinking span into (token-based). +# Used only when n_hops is not provided. +SPLIT_HOP_NUM_SEGMENTS: int = 5 + + +def _split_span_equal(start: int, end: int, num_segments: int) -> List[Tuple[int, int]]: + """Split an inclusive span [start, end] into up to num_segments equal-size segments.""" + start_i = int(start) + end_i = int(end) + if end_i < start_i: + return [] + + length = end_i - start_i + 1 + n = max(1, int(num_segments)) + base = length // n + rem = length % n + + segments: List[Tuple[int, int]] = [] + cur = start_i + for i in range(n): + seg_len = base + (1 if i < rem else 0) + if seg_len <= 0: + continue + seg_start = cur + seg_end = cur + seg_len - 1 + segments.append((seg_start, seg_end)) + cur = seg_end + 1 + return segments + + +@dataclass +class SplitHopConfig: + num_segments: int + + +class LLMIFRAttributionSplitHop(llm_attr.LLMIFRAttribution): + """Experimental FT-IFR variant that split-hops over a segmented thinking span. + + This implementation follows "scheme B": + - The model forward pass is unchanged (no token deletion). + - Attribution remains token-level and prompt-only (via the same observation mask as multi-hop FT-IFR). + - The thinking span is split into equal-length token segments; we propagate attribution mass backward + segment-by-segment, redistributing each segment's pending mass to earlier segments and the prompt. + """ + + def _split_hop_config(self, *, num_segments: int) -> SplitHopConfig: + return SplitHopConfig(num_segments=int(num_segments)) + + @torch.no_grad() + def calculate_ifr_multi_hop_split_hop( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_span: Optional[Tuple[int, int]] = None, + thinking_span: Optional[Tuple[int, int]] = None, + n_hops: int = 1, + renorm_threshold: Optional[float] = None, + observation_mask: Optional[torch.Tensor | Sequence[float]] = None, + ) -> llm_attr.LLMAttributionResult: + input_ids_all, attn_mask, prompt_len_full, gen_len = self._ensure_generation(prompt, target) + total_len = int(input_ids_all.shape[1]) + + num_segments = int(n_hops) if n_hops is not None else int(SPLIT_HOP_NUM_SEGMENTS) + if num_segments < 0: + num_segments = 0 + + if gen_len == 0: + empty = torch.zeros((0, total_len), dtype=torch.float32) + metadata = { + "ifr": { + "type": "multi_hop_split_hop", + "sink_span_generation": sink_span, + "thinking_span_generation": thinking_span, + "renorm_threshold": renorm_threshold, + "split_hop_config": self._split_hop_config(num_segments=num_segments).__dict__, + "note": "No generation tokens; returning empty attribution matrix.", + } + } + return self._finalize_result(empty, metadata=metadata) + + if sink_span is None: + sink_span = (0, gen_len - 1) + span_start, span_end = sink_span + if span_start < 0 or span_end < span_start or span_end >= gen_len: + raise ValueError(f"Invalid sink_span ({span_start}, {span_end}) for generation length {gen_len}.") + + if thinking_span is None: + thinking_span = sink_span + think_start, think_end = thinking_span + if think_start < 0 or think_end < think_start or think_end >= gen_len: + raise ValueError(f"Invalid thinking_span ({think_start}, {think_end}) for generation length {gen_len}.") + + sink_start_abs = int(prompt_len_full) + int(span_start) + sink_end_abs = int(prompt_len_full) + int(span_end) + think_start_abs = int(prompt_len_full) + int(think_start) + think_end_abs = int(prompt_len_full) + int(think_end) + + obs_mask_tensor: Optional[torch.Tensor] = None + if observation_mask is not None: + obs_mask_tensor = torch.as_tensor(observation_mask, dtype=torch.float32) + if obs_mask_tensor.ndim != 1: + raise ValueError("observation_mask must be a 1D tensor or sequence.") + if obs_mask_tensor.numel() == gen_len: + mask_full = torch.zeros(total_len, dtype=torch.float32) + mask_full[int(prompt_len_full) : int(prompt_len_full) + int(gen_len)] = obs_mask_tensor + obs_mask_tensor = mask_full + elif obs_mask_tensor.numel() != total_len: + raise ValueError( + f"observation_mask must have length {gen_len} (generation) or {total_len} (full sequence)." + ) + + cache, attentions, metadata, weight_pack = self._capture_model_state( + input_ids_all, attn_mask, recompute_attention=self.recompute_attention, + ) + params = self._build_ifr_params(metadata, total_len) + renorm = self.renorm_threshold_default if renorm_threshold is None else float(renorm_threshold) + + base_ifr_raw = compute_ifr_sentence_aggregate( + sink_start=sink_start_abs, + sink_end=sink_end_abs, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + rotary_emb=metadata.rotary_emb, + ) + base_total = base_ifr_raw.token_importance_total.to(dtype=torch.float32) + base_ifr = IFRAggregate( + per_layer=base_ifr_raw.per_layer, + token_importance_total=base_total, + head_importance_total=base_ifr_raw.head_importance_total, + ffn_importance_per_layer=base_ifr_raw.ffn_importance_per_layer, + resid_ffn_importance_per_layer=base_ifr_raw.resid_ffn_importance_per_layer, + ) + + if obs_mask_tensor is None: + obs_mask = torch.ones((total_len,), dtype=torch.float32) + obs_mask[int(think_start_abs) : min(int(think_end_abs) + 1, total_len)] = 0.0 + obs_mask[int(sink_start_abs) : min(int(sink_end_abs) + 1, total_len)] = 0.0 + if int(think_end_abs) + 1 < total_len: + obs_mask[int(think_end_abs) + 1 :] = 0.0 + else: + obs_mask = obs_mask_tensor.clone().to(dtype=torch.float32) + if int(obs_mask.shape[0]) != int(total_len): + raise ValueError("observation_mask must match sequence length.") + + base_obs = base_total.clone() * obs_mask + obs_accum = base_obs.clone() + per_hop_obs: List[torch.Tensor] = [] + + if num_segments <= 0: + segments_gen = [] + else: + segments_gen = _split_span_equal(int(think_start), int(think_end), num_segments) + segments_abs: List[Tuple[int, int]] = [ + (int(prompt_len_full) + int(s), int(prompt_len_full) + int(e)) for s, e in segments_gen + ] + + # Pending mass (scheme B): start from hop0 mass on each segment and redistribute backward. + pending_weights: List[torch.Tensor] = [ + base_total[s_abs : e_abs + 1].clone().to(dtype=torch.float32) for (s_abs, e_abs) in segments_abs + ] + + raw_attributions: List[IFRAggregate] = [base_ifr] + hop_details: List[Dict[str, Any]] = [] + + # Process segments from last to first: cot[K-1] -> cot[K-2] -> ... -> cot[0] -> prompt + for seg_idx in range(len(segments_abs) - 1, -1, -1): + seg_start_abs, seg_end_abs = segments_abs[seg_idx] + w_pending = pending_weights[seg_idx] + pending_mass = float(w_pending.sum().item()) + + if pending_mass <= 0.0: + raw_attributions.append( + IFRAggregate( + per_layer=[], + token_importance_total=torch.zeros_like(base_total), + head_importance_total=torch.zeros_like(base_ifr.head_importance_total), + ffn_importance_per_layer=torch.zeros_like(base_ifr.ffn_importance_per_layer), + resid_ffn_importance_per_layer=torch.zeros_like(base_ifr.resid_ffn_importance_per_layer), + ) + ) + per_hop_obs.append(torch.zeros_like(base_total)) + hop_details.append( + { + "segment_index": int(seg_idx), + "segment_span_generation": segments_gen[seg_idx], + "segment_span_absolute": (int(seg_start_abs), int(seg_end_abs)), + "pending_mass": float(pending_mass), + "masked_denom": 0.0, + "alpha": 0.0, + } + ) + continue + + hop_ifr_raw = compute_ifr_sentence_aggregate( + sink_start=int(seg_start_abs), + sink_end=int(seg_end_abs), + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + sink_weights=w_pending.to(dtype=params.model_dtype), + rotary_emb=metadata.rotary_emb, + ) + + hop_total = hop_ifr_raw.token_importance_total.to(dtype=torch.float32) + hop_total_masked = hop_total.clone() + hop_total_masked[int(seg_start_abs) : int(seg_end_abs) + 1] = 0.0 + + masked_denom = float(hop_total_masked.sum().item()) + alpha = float(pending_mass) / (masked_denom + 1e-12) if masked_denom > 0.0 else 0.0 + distributed = hop_total_masked * alpha + + # Prompt-only observation accumulation (generation+thinking excluded by obs_mask). + obs_only = distributed * obs_mask + obs_accum += obs_only + per_hop_obs.append(obs_only) + + # Redistribute mass to earlier segments for further propagation. + if alpha > 0.0: + for j in range(seg_idx): + js_abs, je_abs = segments_abs[j] + pending_weights[j] = pending_weights[j] + distributed[js_abs : je_abs + 1] + pending_weights[seg_idx] = torch.zeros_like(pending_weights[seg_idx]) + + hop_ifr = IFRAggregate( + per_layer=hop_ifr_raw.per_layer, + token_importance_total=hop_total_masked, + head_importance_total=hop_ifr_raw.head_importance_total, + ffn_importance_per_layer=hop_ifr_raw.ffn_importance_per_layer, + resid_ffn_importance_per_layer=hop_ifr_raw.resid_ffn_importance_per_layer, + ) + raw_attributions.append(hop_ifr) + hop_details.append( + { + "segment_index": int(seg_idx), + "segment_span_generation": segments_gen[seg_idx], + "segment_span_absolute": (int(seg_start_abs), int(seg_end_abs)), + "pending_mass": float(pending_mass), + "masked_denom": float(masked_denom), + "alpha": float(alpha), + } + ) + + obs_avg = obs_accum / float(max(1, len(per_hop_obs))) + observation: Dict[str, torch.Tensor | List[torch.Tensor]] = { + "mask": obs_mask, + "base": base_obs, + "per_hop": per_hop_obs, + "sum": obs_accum, + "avg": obs_avg, + } + + multi_hop = MultiHopIFRResult(raw_attributions=raw_attributions, thinking_ratios=[], observation=observation) + eval_vector = multi_hop.observation["sum"] + + score_array = torch.full((gen_len, total_len), torch.nan, dtype=torch.float32) + for offset in range(int(span_start), int(span_end) + 1): + score_array[offset] = eval_vector + + projected_per_hop = [self._project_vector(result.token_importance_total) for result in multi_hop.raw_attributions] + obs = multi_hop.observation + observation_projected = { + "mask": self.extract_user_prompt_attributions(self.prompt_tokens, obs["mask"].view(1, -1))[0], + "base": self._project_vector(obs["base"]), + "sum": self._project_vector(obs["sum"]), + "avg": self._project_vector(obs["avg"]), + "per_hop": [self._project_vector(vec) for vec in obs["per_hop"]], + } + + meta: Dict[str, Any] = { + "ifr": { + "type": "multi_hop_split_hop", + "sink_span_generation": (int(span_start), int(span_end)), + "sink_span_absolute": (int(sink_start_abs), int(sink_end_abs)), + "thinking_span_generation": (int(think_start), int(think_end)), + "thinking_span_absolute": (int(think_start_abs), int(think_end_abs)), + "renorm_threshold": float(renorm), + "split_hop_config": self._split_hop_config(num_segments=num_segments).__dict__, + "segments_generation": [(int(s), int(e)) for (s, e) in segments_gen], + "segments_absolute": [(int(s), int(e)) for (s, e) in segments_abs], + "hop_details": hop_details, + "per_hop_projected": projected_per_hop, + "observation_projected": observation_projected, + "raw": multi_hop, + } + } + + return self._finalize_result(score_array, metadata=meta) + +### both + +class LLMIFRAttributionBoth(llm_attr.LLMIFRAttribution): + """Experimental FT-IFR variant combining stop-token soft deletion with in_all_gen multi-hop. + + Notes + ----- + - Internally, hop0 and subsequent hops aggregate over all_gen_span (= CoT + output). + - The EOS token (assumed to be the last generation token) is excluded from all spans. + - Stop tokens are soft-deleted from hop aggregation weights and observation vectors. + - Returned attribution matrix follows scheme B (rows filled for sink_span_generation). + """ + + def _stop_config(self) -> StopTokenConfig: + return StopTokenConfig( + stop_tokens=list(STOP_TOKENS), + skip_whitespace=bool(SKIP_WHITESPACE), + strip_before_match=bool(STRIP_BEFORE_MATCH), + ) + + @torch.no_grad() + def calculate_ifr_multi_hop_both( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_span: Optional[Tuple[int, int]] = None, + thinking_span: Optional[Tuple[int, int]] = None, + n_hops: int = 1, + renorm_threshold: Optional[float] = None, + observation_mask: Optional[torch.Tensor | Sequence[float]] = None, + ) -> llm_attr.LLMAttributionResult: + input_ids_all, attn_mask, prompt_len_full, gen_len = self._ensure_generation(prompt, target) + total_len = int(input_ids_all.shape[1]) + + if gen_len == 0: + empty = torch.zeros((0, total_len), dtype=torch.float32) + metadata = { + "ifr": { + "type": "multi_hop_both", + "sink_span_generation": sink_span, + "thinking_span_generation": thinking_span, + "renorm_threshold": renorm_threshold, + "stop_config": self._stop_config().__dict__, + "note": "No generation tokens; returning empty attribution matrix.", + } + } + return self._finalize_result(empty, metadata=metadata) + + end_no_eos = _last_attributable_generation_index( + self.tokenizer, + self.generation_ids, + list(getattr(self, "generation_tokens", []) or []), + ) + if end_no_eos < 0: + score_array = torch.full((int(gen_len), total_len), torch.nan, dtype=torch.float32) + metadata = { + "ifr": { + "type": "multi_hop_both", + "sink_span_generation": sink_span, + "thinking_span_generation": thinking_span, + "renorm_threshold": renorm_threshold, + "stop_config": self._stop_config().__dict__, + "note": "No non-EOS generation tokens; returning NaN attribution matrix.", + } + } + return self._finalize_result(score_array, metadata=metadata) + + # Scheme B: fill only sink_span rows; default to all_gen_span. + if sink_span is None: + span_start, span_end = (0, end_no_eos) + else: + span_start, span_end = sink_span + if span_start < 0 or span_end < span_start or span_end > end_no_eos: + raise ValueError( + f"Invalid sink_span ({span_start}, {span_end}) for generation length {gen_len} with EOS excluded." + ) + + think_start_abs: Optional[int] = None + think_end_abs: Optional[int] = None + if thinking_span is not None: + think_start, think_end = thinking_span + if think_start < 0 or think_end < think_start or think_end > end_no_eos: + raise ValueError( + f"Invalid thinking_span ({think_start}, {think_end}) for generation length {gen_len} with EOS excluded." + ) + think_start_abs = int(prompt_len_full) + int(think_start) + think_end_abs = int(prompt_len_full) + int(think_end) + + # Internal hop span: CoT+output when both spans are provided; otherwise default all_gen. + if sink_span is not None and thinking_span is not None: + all_gen_start = min(int(span_start), int(thinking_span[0])) + all_gen_end = max(int(span_end), int(thinking_span[1])) + else: + all_gen_start = 0 + all_gen_end = int(end_no_eos) + + all_gen_start = max(0, int(all_gen_start)) + all_gen_end = min(int(end_no_eos), int(all_gen_end)) + if all_gen_end < all_gen_start: + raise ValueError("Derived all_gen_span is empty after EOS exclusion and bounds checking.") + + sink_start_abs = int(prompt_len_full) + int(span_start) + sink_end_abs = int(prompt_len_full) + int(span_end) + all_gen_start_abs = int(prompt_len_full) + int(all_gen_start) + all_gen_end_abs = int(prompt_len_full) + int(all_gen_end) + + obs_mask_tensor: Optional[torch.Tensor] = None + if observation_mask is not None: + obs_mask_tensor = torch.as_tensor(observation_mask, dtype=torch.float32) + if obs_mask_tensor.ndim != 1: + raise ValueError("observation_mask must be a 1D tensor or sequence.") + if obs_mask_tensor.numel() == gen_len: + mask_full = torch.zeros(total_len, dtype=torch.float32) + mask_full[int(prompt_len_full) : int(prompt_len_full) + int(gen_len)] = obs_mask_tensor + obs_mask_tensor = mask_full + elif obs_mask_tensor.numel() != total_len: + raise ValueError( + f"observation_mask must have length {gen_len} (generation) or {total_len} (full sequence)." + ) + + stop_keep_mask_full = _build_stop_keep_mask_full( + prompt_len_full=int(prompt_len_full), + gen_len=int(gen_len), + user_prompt_indices=list(getattr(self, "user_prompt_indices", []) or []), + user_prompt_tokens=list(getattr(self, "user_prompt_tokens", []) or []), + generation_tokens=list(getattr(self, "generation_tokens", []) or []), + ) + + cache, attentions, metadata, weight_pack = self._capture_model_state( + input_ids_all, attn_mask, recompute_attention=self.recompute_attention, + ) + params = self._build_ifr_params(metadata, total_len) + renorm = self.renorm_threshold_default if renorm_threshold is None else float(renorm_threshold) + + hop_count = max(0, int(n_hops)) + + # Base hop: aggregate over all_gen_span, excluding stop tokens from the sink weights. + gen_tokens = list(getattr(self, "generation_tokens", []) or []) + span_stops = [] + for gi in range(int(all_gen_start), int(all_gen_end) + 1): + tok = gen_tokens[gi] if 0 <= gi < len(gen_tokens) else "" + span_stops.append(is_stop_token(tok)) + base_weights = None + if any(span_stops): + base_weights = torch.as_tensor( + [0.0 if st else 1.0 for st in span_stops], + dtype=params.model_dtype, + ) + + base_ifr_raw = compute_ifr_sentence_aggregate( + sink_start=all_gen_start_abs, + sink_end=all_gen_end_abs, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + sink_weights=base_weights, + rotary_emb=metadata.rotary_emb, + ) + base_total = torch.nan_to_num( + base_ifr_raw.token_importance_total.to(dtype=torch.float32), + nan=0.0, + posinf=0.0, + neginf=0.0, + ) + base_total = base_total * stop_keep_mask_full + base_ifr = IFRAggregate( + per_layer=base_ifr_raw.per_layer, + token_importance_total=base_total, + head_importance_total=base_ifr_raw.head_importance_total, + ffn_importance_per_layer=base_ifr_raw.ffn_importance_per_layer, + resid_ffn_importance_per_layer=base_ifr_raw.resid_ffn_importance_per_layer, + ) + + # Observation mask: respect provided observation_mask, otherwise follow in_all_gen scheme B, + # and then apply stop-token masking so stop tokens are removed from the observation path. + if obs_mask_tensor is None: + obs_mask = torch.ones((total_len,), dtype=torch.float32) + obs_mask[int(all_gen_start_abs) : min(int(all_gen_end_abs) + 1, total_len)] = 0.0 + if int(all_gen_end_abs) + 1 < total_len: + obs_mask[int(all_gen_end_abs) + 1 :] = 0.0 + else: + obs_mask = obs_mask_tensor.clone().to(dtype=torch.float32) + if int(obs_mask.shape[0]) != int(total_len): + raise ValueError("observation_mask must match sequence length.") + + obs_mask = obs_mask * stop_keep_mask_full + + base_obs = base_total.clone() * obs_mask + obs_accum = base_obs.clone() + per_hop_obs: List[torch.Tensor] = [] + + raw_attributions: List[IFRAggregate] = [base_ifr] + + denom_base = float(base_total.sum().item()) + w_span_raw = base_total[int(all_gen_start_abs) : int(all_gen_end_abs) + 1].detach().clone() + w_span_raw = torch.nan_to_num(w_span_raw, nan=0.0, posinf=0.0, neginf=0.0) + w_span_sum = float(w_span_raw.sum().item()) + w_span_weights = ( + (w_span_raw / (w_span_sum + 1e-12)) + if w_span_sum > 0.0 + else torch.zeros_like(w_span_raw, dtype=torch.float32) + ) + current_ratio = float(w_span_sum) / (denom_base + 1e-12) if denom_base > 0.0 else 0.0 + ratios: List[float] = [float(current_ratio)] + + for hop in range(1, hop_count + 1): + if float(w_span_sum) <= 0.0 or float(current_ratio) <= 0.0: + zeros = torch.zeros_like(base_total) + for _ in range(hop, hop_count + 1): + raw_attributions.append( + IFRAggregate( + per_layer=[], + token_importance_total=zeros, + head_importance_total=torch.zeros_like(base_ifr.head_importance_total), + ffn_importance_per_layer=torch.zeros_like(base_ifr.ffn_importance_per_layer), + resid_ffn_importance_per_layer=torch.zeros_like(base_ifr.resid_ffn_importance_per_layer), + ) + ) + per_hop_obs.append(torch.zeros_like(base_total)) + ratios.append(0.0) + break + + hop_ifr_raw = compute_ifr_sentence_aggregate( + sink_start=all_gen_start_abs, + sink_end=all_gen_end_abs, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + sink_weights=w_span_weights, + rotary_emb=metadata.rotary_emb, + ) + + hop_total = torch.nan_to_num( + hop_ifr_raw.token_importance_total.to(dtype=torch.float32), + nan=0.0, + posinf=0.0, + neginf=0.0, + ) + hop_total = hop_total * stop_keep_mask_full + hop_ifr = IFRAggregate( + per_layer=hop_ifr_raw.per_layer, + token_importance_total=hop_total, + head_importance_total=hop_ifr_raw.head_importance_total, + ffn_importance_per_layer=hop_ifr_raw.ffn_importance_per_layer, + resid_ffn_importance_per_layer=hop_ifr_raw.resid_ffn_importance_per_layer, + ) + raw_attributions.append(hop_ifr) + + obs_only = hop_total * obs_mask * float(current_ratio) + obs_accum += obs_only + per_hop_obs.append(obs_only) + + w_span_raw = hop_total[int(all_gen_start_abs) : int(all_gen_end_abs) + 1].detach().clone() + w_span_raw = torch.nan_to_num(w_span_raw, nan=0.0, posinf=0.0, neginf=0.0) + w_span_sum = float(w_span_raw.sum().item()) + w_span_weights = ( + (w_span_raw / (w_span_sum + 1e-12)) + if w_span_sum > 0.0 + else torch.zeros_like(w_span_raw, dtype=torch.float32) + ) + + hop_denom = float(hop_total.sum().item()) + if hop_denom <= 0.0: + current_ratio = 0.0 + else: + current_ratio *= float(w_span_sum) / (hop_denom + 1e-12) + ratios.append(float(current_ratio)) + + obs_avg = obs_accum / float(max(1, hop_count)) + observation: Dict[str, torch.Tensor | List[torch.Tensor]] = { + "mask": obs_mask, + "base": base_obs, + "per_hop": per_hop_obs, + "sum": obs_accum, + "avg": obs_avg, + } + + multi_hop = MultiHopIFRResult(raw_attributions=raw_attributions, thinking_ratios=ratios, observation=observation) + eval_vector = multi_hop.observation["sum"] + + score_array = torch.full((int(gen_len), total_len), torch.nan, dtype=torch.float32) + for offset in range(int(span_start), int(span_end) + 1): + tok = gen_tokens[offset] if 0 <= offset < len(gen_tokens) else "" + if is_stop_token(tok): + continue + score_array[offset] = eval_vector + + projected_per_hop = [self._project_vector(result.token_importance_total) for result in multi_hop.raw_attributions] + obs = multi_hop.observation + observation_projected = { + "mask": self.extract_user_prompt_attributions(self.prompt_tokens, obs["mask"].view(1, -1))[0], + "base": self._project_vector(obs["base"]), + "sum": self._project_vector(obs["sum"]), + "avg": self._project_vector(obs["avg"]), + "per_hop": [self._project_vector(vec) for vec in obs["per_hop"]], + } + + meta: Dict[str, Any] = { + "ifr": { + "type": "multi_hop_both", + "sink_span_generation": (int(span_start), int(span_end)), + "sink_span_absolute": (int(sink_start_abs), int(sink_end_abs)), + "thinking_span_generation": ( + (int(thinking_span[0]), int(thinking_span[1])) if thinking_span is not None else None + ), + "thinking_span_absolute": ( + (int(think_start_abs), int(think_end_abs)) if think_start_abs is not None else None + ), + "all_gen_span_generation": (int(all_gen_start), int(all_gen_end)), + "all_gen_span_absolute": (int(all_gen_start_abs), int(all_gen_end_abs)), + "renorm_threshold": float(renorm), + "n_hops": int(n_hops), + "thinking_ratios": multi_hop.thinking_ratios, + "per_hop_projected": projected_per_hop, + "observation_projected": observation_projected, + "stop_config": self._stop_config().__dict__, + "raw": multi_hop, + "note": "both = stop_words + in_all_gen (scheme B; hops over all_gen_span with EOS excluded).", + } + } + + return self._finalize_result(score_array, metadata=meta) + +### in_all_gen + +class LLMIFRAttributionInAllGen(llm_attr.LLMIFRAttribution): + """Experimental FT-IFR variant that runs all hops over the full generation span (CoT + output). + + Notes + ----- + This method follows scheme B for compatibility: + - Internally, hop0 and subsequent hops aggregate over all_gen_span (= CoT + output). + - The returned attribution matrix is still written only for `sink_span` rows (answer tokens), + falling back to all_gen_span when `sink_span` is not provided. + - The EOS token (assumed to be the last generation token) is excluded from all spans. + """ + + @torch.no_grad() + def calculate_ifr_in_all_gen( + self, + prompt: str, + target: Optional[str] = None, + *, + sink_span: Optional[Tuple[int, int]] = None, + thinking_span: Optional[Tuple[int, int]] = None, + n_hops: int = 1, + renorm_threshold: Optional[float] = None, + observation_mask: Optional[torch.Tensor | Sequence[float]] = None, + ) -> llm_attr.LLMAttributionResult: + input_ids_all, attn_mask, prompt_len_full, gen_len = self._ensure_generation(prompt, target) + total_len = int(input_ids_all.shape[1]) + + if gen_len == 0: + empty = torch.zeros((0, total_len), dtype=torch.float32) + metadata = { + "ifr": { + "type": "in_all_gen", + "sink_span_generation": sink_span, + "thinking_span_generation": thinking_span, + "renorm_threshold": renorm_threshold, + "note": "No generation tokens; returning empty attribution matrix.", + } + } + return self._finalize_result(empty, metadata=metadata) + + end_no_eos = _last_attributable_generation_index( + self.tokenizer, + self.generation_ids, + list(getattr(self, "generation_tokens", []) or []), + ) + if end_no_eos < 0: + score_array = torch.full((int(gen_len), total_len), torch.nan, dtype=torch.float32) + metadata = { + "ifr": { + "type": "in_all_gen", + "sink_span_generation": sink_span, + "thinking_span_generation": thinking_span, + "renorm_threshold": renorm_threshold, + "note": "No non-EOS generation tokens; returning NaN attribution matrix.", + } + } + return self._finalize_result(score_array, metadata=metadata) + + # Scheme B: fill only sink_span rows; default to all_gen_span. + if sink_span is None: + span_start, span_end = (0, end_no_eos) + else: + span_start, span_end = sink_span + if span_start < 0 or span_end < span_start or span_end > end_no_eos: + raise ValueError( + f"Invalid sink_span ({span_start}, {span_end}) for generation length {gen_len} with EOS excluded." + ) + + think_start_abs: Optional[int] = None + think_end_abs: Optional[int] = None + if thinking_span is not None: + think_start, think_end = thinking_span + if think_start < 0 or think_end < think_start or think_end > end_no_eos: + raise ValueError( + f"Invalid thinking_span ({think_start}, {think_end}) for generation length {gen_len} with EOS excluded." + ) + think_start_abs = int(prompt_len_full) + int(think_start) + think_end_abs = int(prompt_len_full) + int(think_end) + + # Internal hop span: CoT+output when both spans are provided; otherwise default all_gen. + if sink_span is not None and thinking_span is not None: + all_gen_start = min(int(span_start), int(thinking_span[0])) + all_gen_end = max(int(span_end), int(thinking_span[1])) + else: + all_gen_start = 0 + all_gen_end = int(end_no_eos) + + all_gen_start = max(0, int(all_gen_start)) + all_gen_end = min(int(end_no_eos), int(all_gen_end)) + if all_gen_end < all_gen_start: + raise ValueError("Derived all_gen_span is empty after EOS exclusion and bounds checking.") + + sink_start_abs = int(prompt_len_full) + int(span_start) + sink_end_abs = int(prompt_len_full) + int(span_end) + all_gen_start_abs = int(prompt_len_full) + int(all_gen_start) + all_gen_end_abs = int(prompt_len_full) + int(all_gen_end) + + obs_mask_tensor: Optional[torch.Tensor] = None + if observation_mask is not None: + obs_mask_tensor = torch.as_tensor(observation_mask, dtype=torch.float32) + if obs_mask_tensor.ndim != 1: + raise ValueError("observation_mask must be a 1D tensor or sequence.") + if obs_mask_tensor.numel() == gen_len: + mask_full = torch.zeros(total_len, dtype=torch.float32) + mask_full[int(prompt_len_full) : int(prompt_len_full) + int(gen_len)] = obs_mask_tensor + obs_mask_tensor = mask_full + elif obs_mask_tensor.numel() != total_len: + raise ValueError( + f"observation_mask must have length {gen_len} (generation) or {total_len} (full sequence)." + ) + + cache, attentions, metadata, weight_pack = self._capture_model_state( + input_ids_all, attn_mask, recompute_attention=self.recompute_attention, + ) + params = self._build_ifr_params(metadata, total_len) + renorm = self.renorm_threshold_default if renorm_threshold is None else float(renorm_threshold) + + # Multi-hop IFR over all_gen_span (scheme B). We implement the hop loop inline + # to robustly handle rare NaNs in intermediate IFR vectors on long sequences. + hop_count = max(0, int(n_hops)) + + base_ifr_raw = compute_ifr_sentence_aggregate( + sink_start=all_gen_start_abs, + sink_end=all_gen_end_abs, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + rotary_emb=metadata.rotary_emb, + ) + base_total = torch.nan_to_num( + base_ifr_raw.token_importance_total.to(dtype=torch.float32), + nan=0.0, + posinf=0.0, + neginf=0.0, + ) + base_ifr = IFRAggregate( + per_layer=base_ifr_raw.per_layer, + token_importance_total=base_total, + head_importance_total=base_ifr_raw.head_importance_total, + ffn_importance_per_layer=base_ifr_raw.ffn_importance_per_layer, + resid_ffn_importance_per_layer=base_ifr_raw.resid_ffn_importance_per_layer, + ) + + if obs_mask_tensor is None: + obs_mask = torch.ones((total_len,), dtype=torch.float32) + obs_mask[int(all_gen_start_abs) : min(int(all_gen_end_abs) + 1, total_len)] = 0.0 + if int(all_gen_end_abs) + 1 < total_len: + obs_mask[int(all_gen_end_abs) + 1 :] = 0.0 + else: + obs_mask = obs_mask_tensor.clone().to(dtype=torch.float32) + if int(obs_mask.shape[0]) != int(total_len): + raise ValueError("observation_mask must match sequence length.") + + base_obs = base_total.clone() * obs_mask + obs_accum = base_obs.clone() + per_hop_obs: List[torch.Tensor] = [] + + raw_attributions: List[IFRAggregate] = [base_ifr] + + denom_base = float(base_total.sum().item()) + w_span_raw = base_total[int(all_gen_start_abs) : int(all_gen_end_abs) + 1].detach().clone() + w_span_raw = torch.nan_to_num(w_span_raw, nan=0.0, posinf=0.0, neginf=0.0) + w_span_sum = float(w_span_raw.sum().item()) + w_span_weights = ( + (w_span_raw / (w_span_sum + 1e-12)) + if w_span_sum > 0.0 + else torch.zeros_like(w_span_raw, dtype=torch.float32) + ) + current_ratio = float(w_span_sum) / (denom_base + 1e-12) if denom_base > 0.0 else 0.0 + ratios: List[float] = [float(current_ratio)] + + for hop in range(1, hop_count + 1): + if float(w_span_sum) <= 0.0 or float(current_ratio) <= 0.0: + zeros = torch.zeros_like(base_total) + for _ in range(hop, hop_count + 1): + raw_attributions.append( + IFRAggregate( + per_layer=[], + token_importance_total=zeros, + head_importance_total=torch.zeros_like(base_ifr.head_importance_total), + ffn_importance_per_layer=torch.zeros_like(base_ifr.ffn_importance_per_layer), + resid_ffn_importance_per_layer=torch.zeros_like(base_ifr.resid_ffn_importance_per_layer), + ) + ) + per_hop_obs.append(torch.zeros_like(base_total)) + ratios.append(0.0) + break + + hop_ifr_raw = compute_ifr_sentence_aggregate( + sink_start=all_gen_start_abs, + sink_end=all_gen_end_abs, + cache=cache, + attentions=attentions, + weight_pack=weight_pack, + params=params, + renorm_threshold=renorm, + sink_weights=w_span_weights, + rotary_emb=metadata.rotary_emb, + ) + + hop_total = torch.nan_to_num( + hop_ifr_raw.token_importance_total.to(dtype=torch.float32), + nan=0.0, + posinf=0.0, + neginf=0.0, + ) + hop_ifr = IFRAggregate( + per_layer=hop_ifr_raw.per_layer, + token_importance_total=hop_total, + head_importance_total=hop_ifr_raw.head_importance_total, + ffn_importance_per_layer=hop_ifr_raw.ffn_importance_per_layer, + resid_ffn_importance_per_layer=hop_ifr_raw.resid_ffn_importance_per_layer, + ) + raw_attributions.append(hop_ifr) + + obs_only = hop_total * obs_mask * float(current_ratio) + obs_accum += obs_only + per_hop_obs.append(obs_only) + + w_span_raw = hop_total[int(all_gen_start_abs) : int(all_gen_end_abs) + 1].detach().clone() + w_span_raw = torch.nan_to_num(w_span_raw, nan=0.0, posinf=0.0, neginf=0.0) + w_span_sum = float(w_span_raw.sum().item()) + w_span_weights = ( + (w_span_raw / (w_span_sum + 1e-12)) + if w_span_sum > 0.0 + else torch.zeros_like(w_span_raw, dtype=torch.float32) + ) + + hop_denom = float(hop_total.sum().item()) + if hop_denom <= 0.0: + current_ratio = 0.0 + else: + current_ratio *= float(w_span_sum) / (hop_denom + 1e-12) + ratios.append(float(current_ratio)) + + obs_avg = obs_accum / float(max(1, hop_count)) + observation: Dict[str, torch.Tensor | List[torch.Tensor]] = { + "mask": obs_mask, + "base": base_obs, + "per_hop": per_hop_obs, + "sum": obs_accum, + "avg": obs_avg, + } + + multi_hop = MultiHopIFRResult(raw_attributions=raw_attributions, thinking_ratios=ratios, observation=observation) + + eval_vector = multi_hop.observation["sum"] + score_array = torch.full((int(gen_len), total_len), torch.nan, dtype=torch.float32) + for offset in range(int(span_start), int(span_end) + 1): + score_array[offset] = eval_vector + + projected_per_hop = [self._project_vector(result.token_importance_total) for result in multi_hop.raw_attributions] + obs = multi_hop.observation + observation_projected = { + "mask": self.extract_user_prompt_attributions(self.prompt_tokens, obs["mask"].view(1, -1))[0], + "base": self._project_vector(obs["base"]), + "sum": self._project_vector(obs["sum"]), + "avg": self._project_vector(obs["avg"]), + "per_hop": [self._project_vector(vec) for vec in obs["per_hop"]], + } + + meta: Dict[str, Any] = { + "ifr": { + "type": "in_all_gen", + "sink_span_generation": (int(span_start), int(span_end)), + "sink_span_absolute": (int(sink_start_abs), int(sink_end_abs)), + "thinking_span_generation": ( + (int(thinking_span[0]), int(thinking_span[1])) if thinking_span is not None else None + ), + "thinking_span_absolute": ( + (int(think_start_abs), int(think_end_abs)) if think_start_abs is not None else None + ), + "all_gen_span_generation": (int(all_gen_start), int(all_gen_end)), + "all_gen_span_absolute": (int(all_gen_start_abs), int(all_gen_end_abs)), + "renorm_threshold": float(renorm), + "n_hops": int(n_hops), + "thinking_ratios": multi_hop.thinking_ratios, + "per_hop_projected": projected_per_hop, + "observation_projected": observation_projected, + "raw": multi_hop, + "note": "scheme B: rows filled for sink_span_generation; hops over all_gen_span (EOS excluded).", + } + } + + return self._finalize_result(score_array, metadata=meta) diff --git a/flashtrace/lrp_patches.py b/flashtrace/lrp_patches.py new file mode 100644 index 0000000000000000000000000000000000000000..8867592aafb5c7d0ac81dc018ee6fee9e6af4a27 --- /dev/null +++ b/flashtrace/lrp_patches.py @@ -0,0 +1,319 @@ +"""LRP forward patches for AttnLRP implementation. + +This module provides patched forward functions for transformer layers +that implement AttnLRP rules during the backward pass: + +- RMSNorm: Identity rule via stopping gradient on variance +- Gated MLP: Identity rule on activation + Uniform rule on gate*up +- Attention: Uniform rule on Q@K^T and attention@V + +Reference: + AttnLRP: Attention-Aware Layer-wise Relevance Propagation for Transformers (ICML 2024) + https://arxiv.org/abs/2402.05602 +""" + +import torch +from contextlib import contextmanager +from typing import Dict, Any, Optional, Callable +from functools import partial + +from .lrp_rules import stop_gradient, divide_gradient, identity_rule_implicit + + +# Model configuration for different architectures +MODEL_CONFIGS = { + "qwen3": { + "modeling_module": "transformers.models.qwen3.modeling_qwen3", + "rms_norm_class": "Qwen3RMSNorm", + "mlp_class": "Qwen3MLP", + }, + "qwen2": { + "modeling_module": "transformers.models.qwen2.modeling_qwen2", + "rms_norm_class": "Qwen2RMSNorm", + "mlp_class": "Qwen2MLP", + }, + "llama": { + "modeling_module": "transformers.models.llama.modeling_llama", + "rms_norm_class": "LlamaRMSNorm", + "mlp_class": "LlamaMLP", + }, +} + + +def rms_norm_forward_lrp(self, hidden_states: torch.Tensor) -> torch.Tensor: + """RMSNorm forward with LRP identity rule. + + On normalization operations, we apply the identity rule by stopping + the gradient flow through the variance calculation. + + This is equivalent to Equation 9 in the AttnLRP paper. + """ + input_dtype = hidden_states.dtype + hidden_states = hidden_states.to(torch.float32) + variance = hidden_states.pow(2).mean(-1, keepdim=True) + # Stop gradient through the normalization factor + hidden_states = hidden_states * stop_gradient(torch.rsqrt(variance + self.variance_epsilon)) + return self.weight * hidden_states.to(input_dtype) + + +def gated_mlp_forward_lrp(self, x: torch.Tensor) -> torch.Tensor: + """Gated MLP forward with LRP rules. + + On the element-wise non-linear activation, we apply the identity rule. + On the element-wise multiplication (gate * up), we apply the uniform rule. + + Both rules are implemented via the Gradient*Input framework. + """ + gate_out = self.gate_proj(x) + # Apply identity rule to the non-linear activation + gate_out = identity_rule_implicit(self.act_fn, gate_out) + + # Element-wise multiplication of gate and up projections + weighted = gate_out * self.up_proj(x) + # Apply uniform rule (divide gradient by 2) + weighted = divide_gradient(weighted, 2) + + return self.down_proj(weighted) + + +def wrap_attention_forward(forward_fn: Callable) -> Callable: + """Wrap an attention forward function with LRP gradient rules. + + Applies the uniform rule to Q, K, V tensors: + - Q and K: divide by 4 (accounts for Q@K^T matmul and softmax) + - V: divide by 2 (accounts for attention@V matmul) + + Parameters + ---------- + forward_fn : Callable + The original attention forward function + + Returns + ------- + Callable + Wrapped attention forward function with LRP rules + """ + def attention_forward_lrp(module, query, key, value, *args, **kwargs): + # Apply uniform rule to Q, K, V + # Factor of 4 for Q/K accounts for two matmuls (Q@K^T, then softmax/attention) + # Factor of 2 for V accounts for single matmul with attention weights + query = divide_gradient(query, 4) + key = divide_gradient(key, 4) + value = divide_gradient(value, 2) + + # Disable dropout during LRP computation + if 'dropout' in kwargs: + kwargs['dropout'] = 0.0 + + return forward_fn(module, query, key, value, *args, **kwargs) + + return attention_forward_lrp + + +def dropout_forward_lrp(self, x: torch.Tensor) -> torch.Tensor: + """Dropout forward that acts as identity. + + During LRP computation, we need gradient checkpointing which requires + train mode, but we don't want actual dropout. This patches dropout + to be identity. + """ + return x + + +class LRPPatchState: + """Stores original module states for restoration after LRP computation.""" + + def __init__(self): + self.original_forwards: Dict[str, Any] = {} + self.original_attention_functions: Dict[str, Dict[str, Callable]] = {} + self.original_eager_attention: Dict[str, Callable] = {} + self.patched = False + + +def _get_modeling_module(model_type: str): + """Dynamically import the modeling module for a given model type.""" + import importlib + config = MODEL_CONFIGS.get(model_type) + if config is None: + raise ValueError(f"Unsupported model type: {model_type}. Supported: {list(MODEL_CONFIGS.keys())}") + return importlib.import_module(config["modeling_module"]) + + +def apply_lrp_patches(model, model_type: str = "qwen3") -> LRPPatchState: + """Apply LRP patches to a model. + + This function patches the forward methods of various layers to implement + AttnLRP rules during backward propagation. + + Parameters + ---------- + model : transformers model + The model to patch + model_type : str + Type of model architecture (qwen3, qwen2, llama) + + Returns + ------- + LRPPatchState + State object containing original methods for restoration + """ + state = LRPPatchState() + config = MODEL_CONFIGS.get(model_type) + + if config is None: + raise ValueError(f"Unsupported model type: {model_type}") + + modeling_module = _get_modeling_module(model_type) + + # Patch RMSNorm layers + rms_norm_cls = getattr(modeling_module, config["rms_norm_class"]) + state.original_forwards[config["rms_norm_class"]] = rms_norm_cls.forward + rms_norm_cls.forward = rms_norm_forward_lrp + + # Patch MLP layers + mlp_cls = getattr(modeling_module, config["mlp_class"]) + state.original_forwards[config["mlp_class"]] = mlp_cls.forward + mlp_cls.forward = gated_mlp_forward_lrp + + # Patch Dropout layers + from torch.nn import Dropout + state.original_forwards["Dropout"] = Dropout.forward + Dropout.forward = dropout_forward_lrp + + # Patch attention functions + if hasattr(modeling_module, 'ALL_ATTENTION_FUNCTIONS'): + state.original_attention_functions[model_type] = dict(modeling_module.ALL_ATTENTION_FUNCTIONS) + new_attention_functions = {} + for key, fn in modeling_module.ALL_ATTENTION_FUNCTIONS.items(): + new_attention_functions[key] = wrap_attention_forward(fn) + modeling_module.ALL_ATTENTION_FUNCTIONS = new_attention_functions + + if hasattr(modeling_module, 'eager_attention_forward'): + state.original_eager_attention[model_type] = modeling_module.eager_attention_forward + modeling_module.eager_attention_forward = wrap_attention_forward( + modeling_module.eager_attention_forward + ) + + state.patched = True + return state + + +def remove_lrp_patches(state: LRPPatchState, model_type: str = "qwen3"): + """Remove LRP patches and restore original forward methods. + + Parameters + ---------- + state : LRPPatchState + State object from apply_lrp_patches + model_type : str + Type of model architecture + """ + if not state.patched: + return + + config = MODEL_CONFIGS.get(model_type) + if config is None: + return + + modeling_module = _get_modeling_module(model_type) + + # Restore RMSNorm + if config["rms_norm_class"] in state.original_forwards: + rms_norm_cls = getattr(modeling_module, config["rms_norm_class"]) + rms_norm_cls.forward = state.original_forwards[config["rms_norm_class"]] + + # Restore MLP + if config["mlp_class"] in state.original_forwards: + mlp_cls = getattr(modeling_module, config["mlp_class"]) + mlp_cls.forward = state.original_forwards[config["mlp_class"]] + + # Restore Dropout + if "Dropout" in state.original_forwards: + from torch.nn import Dropout + Dropout.forward = state.original_forwards["Dropout"] + + # Restore attention functions + if model_type in state.original_attention_functions: + modeling_module.ALL_ATTENTION_FUNCTIONS = state.original_attention_functions[model_type] + + if model_type in state.original_eager_attention: + modeling_module.eager_attention_forward = state.original_eager_attention[model_type] + + state.patched = False + + +@contextmanager +def lrp_context(model, model_type: str = "qwen3"): + """Context manager for applying LRP patches temporarily. + + This is the recommended way to use LRP patches as it ensures + proper cleanup even if an exception occurs. + + Example + ------- + >>> with lrp_context(model, model_type="qwen3"): + ... # Compute forward pass and backward for LRP + ... output = model(inputs_embeds=embeds) + ... output.logits[0, -1, :].max().backward() + ... relevance = (embeds * embeds.grad).sum(-1) + + Parameters + ---------- + model : transformers model + The model to patch + model_type : str + Type of model architecture (qwen3, qwen2, llama) + + Yields + ------ + LRPPatchState + The patch state (usually not needed by caller) + """ + state = apply_lrp_patches(model, model_type) + try: + yield state + finally: + remove_lrp_patches(state, model_type) + + +def detect_model_type(model) -> str: + """Attempt to detect the model type from a model instance. + + Parameters + ---------- + model : transformers model + The model to detect type for + + Returns + ------- + str + Detected model type (qwen3, qwen2, llama) + + Raises + ------ + ValueError + If model type cannot be detected + """ + model_class_name = model.__class__.__name__.lower() + + if 'qwen3' in model_class_name: + return 'qwen3' + elif 'qwen2' in model_class_name: + return 'qwen2' + elif 'llama' in model_class_name: + return 'llama' + + # Check config if available + if hasattr(model, 'config'): + config_name = getattr(model.config, 'model_type', '').lower() + if 'qwen3' in config_name: + return 'qwen3' + elif 'qwen2' in config_name: + return 'qwen2' + elif 'llama' in config_name: + return 'llama' + + raise ValueError( + f"Could not detect model type from {model.__class__.__name__}. " + f"Please specify model_type explicitly. Supported: {list(MODEL_CONFIGS.keys())}" + ) diff --git a/flashtrace/lrp_rules.py b/flashtrace/lrp_rules.py new file mode 100644 index 0000000000000000000000000000000000000000..ba54f622f693d5c97138dcb85aa743636fd67c37 --- /dev/null +++ b/flashtrace/lrp_rules.py @@ -0,0 +1,129 @@ +"""LRP (Layer-wise Relevance Propagation) autograd rules for AttnLRP. + +This module implements the core autograd functions needed for AttnLRP: +- stop_gradient: Stop gradient flow completely +- divide_gradient: Divide gradient by a factor (Uniform Rule from Eq. 7) +- identity_rule_implicit: Handle non-linear activations (Identity Rule from Eq. 9) + +Reference: + AttnLRP: Attention-Aware Layer-wise Relevance Propagation for Transformers (ICML 2024) + https://arxiv.org/abs/2402.05602 +""" + +import torch +from torch.autograd import Function + + +def stop_gradient(input: torch.Tensor) -> torch.Tensor: + """Stop the gradient from flowing through the input tensor. + + This is used in RMSNorm/LayerNorm to stop gradient flow through + the variance calculation, implementing the identity rule. + + Parameters + ---------- + input : torch.Tensor + The input tensor + + Returns + ------- + torch.Tensor + The detached tensor (same values, no gradient) + """ + return input.detach() + + +def divide_gradient(input: torch.Tensor, factor: int = 2) -> torch.Tensor: + """Divide the gradient by a factor during backpropagation. + + Implements the Uniform Rule (Equation 7 from the AttnLRP paper). + Used after matmul or element-wise multiplication operations. + + Parameters + ---------- + input : torch.Tensor + The input tensor + factor : int + The factor to divide the gradient by. Default is 2. + + Returns + ------- + torch.Tensor + The same tensor with modified backward gradient + """ + return DivideGradientFn.apply(input, factor) + + +def identity_rule_implicit(fn, input: torch.Tensor, epsilon: float = 1e-10) -> torch.Tensor: + """Apply the identity rule implicitly through the Gradient*Input framework. + + Implements the Identity Rule (Equation 9 from the AttnLRP paper). + Used for element-wise non-linear activation functions. + + The backward pass computes: gradient = (output / input) * out_relevance + which, when multiplied by input in the final relevance computation, + gives the identity rule: relevance = output * out_relevance / output = out_relevance + + Parameters + ---------- + fn : callable + The non-linear function to apply (e.g., SiLU, GELU) + input : torch.Tensor + The input tensor + epsilon : float + Small constant for numerical stability in division + + Returns + ------- + torch.Tensor + The output of fn(input) with modified backward pass + """ + return IdentityRuleImplicitFn.apply(fn, input, epsilon) + + +class DivideGradientFn(Function): + """Autograd Function that divides gradient by a constant factor. + + Forward pass: identity (returns input unchanged) + Backward pass: divides gradient by factor + + This implements the Uniform Rule for element-wise multiplication + and part of the handling for matrix multiplication. + """ + + @staticmethod + def forward(ctx, input: torch.Tensor, factor: int = 2) -> torch.Tensor: + ctx.factor = factor + return input + + @staticmethod + def backward(ctx, grad_output: torch.Tensor): + return grad_output / ctx.factor, None + + +class IdentityRuleImplicitFn(Function): + """Autograd Function implementing the identity rule for non-linear activations. + + Forward pass: computes fn(input) and saves output/input ratio + Backward pass: multiplies gradient by saved ratio + + This is more efficient than explicit LRP computation because it + leverages the Gradient*Input framework. + """ + + @staticmethod + def forward(ctx, fn, input: torch.Tensor, epsilon: float = 1e-10) -> torch.Tensor: + output = fn(input) + if input.requires_grad: + # Save output/input for backward + # Adding epsilon prevents division by zero + ctx.save_for_backward(output / (input + epsilon)) + return output + + @staticmethod + def backward(ctx, grad_output: torch.Tensor): + # Gradient is scaled by output/input ratio + # When multiplied by input later, this gives the identity rule + ratio = ctx.saved_tensors[0] + gradient = ratio * grad_output + return None, gradient, None diff --git a/flashtrace/model_io.py b/flashtrace/model_io.py new file mode 100644 index 0000000000000000000000000000000000000000..3cf40509962ad6aef09ee059adf11a2c62b7497d --- /dev/null +++ b/flashtrace/model_io.py @@ -0,0 +1,49 @@ +from __future__ import annotations + +from typing import Any + +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer + + +def _resolve_dtype(dtype: str | torch.dtype = "auto") -> str | torch.dtype: + if isinstance(dtype, torch.dtype): + return dtype + value = str(dtype).lower() + if value == "auto": + return "auto" + mapping = { + "float16": torch.float16, + "fp16": torch.float16, + "bfloat16": torch.bfloat16, + "bf16": torch.bfloat16, + "float32": torch.float32, + "fp32": torch.float32, + } + if value not in mapping: + raise ValueError(f"Unsupported dtype: {dtype}") + return mapping[value] + + +def load_model_and_tokenizer( + model_name_or_path: str, + *, + device_map: str | dict[str, Any] | None = "auto", + dtype: str | torch.dtype = "auto", + trust_remote_code: bool = True, + **model_kwargs: Any, +): + """Load a Hugging Face causal LM and matching tokenizer.""" + + tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, trust_remote_code=trust_remote_code) + model = AutoModelForCausalLM.from_pretrained( + model_name_or_path, + torch_dtype=_resolve_dtype(dtype), + device_map=device_map, + trust_remote_code=trust_remote_code, + **model_kwargs, + ) + model.eval() + if tokenizer.pad_token_id is None and tokenizer.eos_token_id is not None: + tokenizer.pad_token = tokenizer.eos_token + return model, tokenizer diff --git a/flashtrace/result.py b/flashtrace/result.py new file mode 100644 index 0000000000000000000000000000000000000000..2857b7888cb48366c74b2cb1aa1b67ed721d4676 --- /dev/null +++ b/flashtrace/result.py @@ -0,0 +1,78 @@ +from __future__ import annotations + +import json +from dataclasses import asdict, dataclass, field, is_dataclass +from pathlib import Path +from typing import Any + + +@dataclass(frozen=True) +class TokenScore: + index: int + token: str + score: float + + +@dataclass(frozen=True) +class TraceResult: + """Public attribution result returned by FlashTrace.""" + + prompt_tokens: list[str] + generation_tokens: list[str] + scores: list[float] + per_hop_scores: list[list[float]] = field(default_factory=list) + thinking_ratios: list[float] = field(default_factory=list) + output_span: tuple[int, int] | None = None + reasoning_span: tuple[int, int] | None = None + method: str = "flashtrace" + metadata: dict[str, Any] = field(default_factory=dict) + + def topk_inputs(self, k: int = 20) -> list[TokenScore]: + limit = max(0, int(k)) + items = [ + TokenScore(index=i, token=tok, score=float(score)) + for i, (tok, score) in enumerate(zip(self.prompt_tokens, self.scores)) + ] + items.sort(key=lambda item: item.score, reverse=True) + return items[:limit] + + def to_dict(self) -> dict[str, Any]: + return { + "method": self.method, + "prompt_tokens": list(self.prompt_tokens), + "generation_tokens": list(self.generation_tokens), + "scores": [float(x) for x in self.scores], + "per_hop_scores": [[float(x) for x in row] for row in self.per_hop_scores], + "thinking_ratios": [float(x) for x in self.thinking_ratios], + "output_span": list(self.output_span) if self.output_span is not None else None, + "reasoning_span": list(self.reasoning_span) if self.reasoning_span is not None else None, + "top_inputs": [asdict(item) for item in self.topk_inputs()], + "metadata": _jsonable(self.metadata), + } + + def to_json(self, path: str | Path) -> None: + target = Path(path) + target.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False), encoding="utf-8") + + def to_html(self, path: str | Path) -> None: + from .viz import render_trace_html + + target = Path(path) + target.write_text(render_trace_html(self), encoding="utf-8") + + +def _jsonable(value: Any) -> Any: + if value is None or isinstance(value, (str, int, float, bool)): + return value + if hasattr(value, "detach") and hasattr(value, "cpu"): + try: + return value.detach().cpu().tolist() + except Exception: + return repr(value) + if is_dataclass(value): + return _jsonable(asdict(value)) + if isinstance(value, dict): + return {str(k): _jsonable(v) for k, v in value.items()} + if isinstance(value, (list, tuple)): + return [_jsonable(v) for v in value] + return repr(value) diff --git a/flashtrace/shared_utils.py b/flashtrace/shared_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..590342c4bbdc3be3c2423772ec06bd7cf0990926 --- /dev/null +++ b/flashtrace/shared_utils.py @@ -0,0 +1,147 @@ +"""Shared utilities for the flashtrace project. + +This module contains common constants, NLP pipeline initialization, +and sentence processing functions used across multiple modules. +""" + +import re +import spacy +from spacy.language import Language +from spacy.tokens import Doc +import torch + +# Common constants +DEFAULT_GENERATE_KWARGS = {"max_new_tokens": 512, "do_sample": False} +DEFAULT_PROMPT_TEMPLATE = "Context:{context}\n\n\nQuery: {query}" + +# Sentence detector - NLP pipeline initialization +try: + nlp = spacy.load("en_core_web_sm") + _newline_pipe_position = {"before": "parser"} +except OSError: + nlp = spacy.blank("en") + if "sentencizer" not in nlp.pipe_names: + nlp.add_pipe("sentencizer") + _newline_pipe_position = {"after": "sentencizer"} if "sentencizer" in nlp.pipe_names else {"last": True} + + +@Language.component("newline_cap_split") +def newline_cap_split(doc: Doc) -> Doc: + """Custom component to split on capitalized words after newline.""" + for i, token in enumerate(doc): + if token.is_title and i > 0: + prev_token = doc[i - 1] + if "\n" in prev_token.text or (prev_token.is_space and "\n" in prev_token.text): + token.is_sent_start = True + return doc + + +# Add to pipeline +nlp.add_pipe("newline_cap_split", **_newline_pipe_position) + + +def create_sentences(text, tokenizer, return_indices=False, show=False) -> list[str]: + """Split text into sentences and return the sentences. + + Args: + text: The text to split into sentences. + tokenizer: The tokenizer to use for EOS token handling. + return_indices: If True, return both sentences and their indices. + show: Unused, kept for backward compatibility. + + Returns: + A list of sentences, or a tuple of (sentences, indices) if return_indices is True. + """ + sentences = [] + separators = [] + indices = [] + + # Process the text with spacy + doc = nlp(text) + + # Extract sentences + sentences = [] + for sent in doc.sents: + sentences.append(sent.text) + + # extract separators + cur_start = 0 + for sentence in sentences: + indices.append(cur_start) + cur_end = text.find(sentence, cur_start) + separator = text[cur_start:cur_end] + separators.append(separator) + cur_start = cur_end + len(sentence) + + # combine the separators with the sentences properly + for i in range(len(sentences)): + if separators[i] == "\n": + sentences[i] = sentences[i] + separators[i] + else: + sentences[i] = separators[i] + sentences[i] + + # if the text had an eos token (generated text) it will be missed + # and attached on the last sentence, so we manually handle it + if tokenizer is not None: + eos = tokenizer.eos_token + if eos and sentences and eos in sentences[-1]: + sentences[-1] = sentences[-1].replace(eos, "") + indices.append(len("".join(sentences))) + sentences.append(eos) + + indices.append(len(text)) + + if return_indices: + return sentences, indices + else: + return sentences + + +def create_sentences_fallback(text, tokenizer=None) -> list[str]: + """Very naive fallback sentence splitter for when spacy is unavailable. + + Split by newline first, then by simple punctuation boundaries. + """ + parts = [] + for block in text.split("\n"): + xs = re.split(r"(?<=[.!?])\s+", block.strip()) if block.strip() else [] + parts.extend([x for x in xs if x]) + return parts or ([text] if text else []) + + +def create_sentence_masks(tokens, sentences, show=False) -> torch.Tensor: + """Create a binary mask of shape [sentences, tokens]. + + Each row has a 1 where a token is in the represented sentence. + + Args: + tokens: List of tokens. + sentences: List of sentences. + show: Unused, kept for backward compatibility. + + Returns: + A tensor mask of shape [len(sentences), len(tokens)]. + """ + mask = torch.zeros((len(sentences), len(tokens))) + + sentence_idx = 0 + sent_pointer = 0 + + for token_idx, token in enumerate(tokens): + current_sentence = sentences[sentence_idx] + + mask[sentence_idx, token_idx] = 1 + + if '\n' in token: + sent_pointer += len(token) + 1 + else: + sent_pointer += len(token) + + if sent_pointer >= len(current_sentence): + sentence_idx += 1 + sent_pointer = 0 + + if sentence_idx >= len(sentences): + break + + return mask diff --git a/flashtrace/tracer.py b/flashtrace/tracer.py new file mode 100644 index 0000000000000000000000000000000000000000..c1c5f663363d226f51eff827e33faaa223c59ebe --- /dev/null +++ b/flashtrace/tracer.py @@ -0,0 +1,155 @@ +from __future__ import annotations + +from typing import Any, Literal + +import torch + +from .attribution import LLMAttributionResult, LLMIFRAttribution +from .improved import LLMIFRAttributionBoth +from .result import TraceResult + +TraceMethod = Literal["flashtrace", "ifr-span", "ifr-matrix"] + + +def _to_float_list(values: Any) -> list[float]: + if torch.is_tensor(values): + values = values.detach().cpu().to(dtype=torch.float32).tolist() + return [float(x) for x in (values or [])] + + +class FlashTrace: + """Public facade for FlashTrace attribution.""" + + def __init__( + self, + model, + tokenizer, + *, + chunk_tokens: int = 128, + sink_chunk_tokens: int = 32, + recompute_attention: bool = False, + generate_kwargs: dict[str, Any] | None = None, + use_chat_template: bool = False, + ) -> None: + self.model = model + self.tokenizer = tokenizer + self.chunk_tokens = int(chunk_tokens) + self.sink_chunk_tokens = int(sink_chunk_tokens) + self.recompute_attention = bool(recompute_attention) + self.generate_kwargs = generate_kwargs + self.use_chat_template = bool(use_chat_template) + + def trace( + self, + *, + prompt: str, + target: str | None = None, + output_span: tuple[int, int] | None = None, + reasoning_span: tuple[int, int] | None = None, + hops: int = 1, + method: TraceMethod = "flashtrace", + renorm_threshold: float | None = None, + ) -> TraceResult: + if method == "flashtrace": + engine = LLMIFRAttributionBoth( + self.model, + self.tokenizer, + generate_kwargs=self.generate_kwargs, + chunk_tokens=self.chunk_tokens, + sink_chunk_tokens=self.sink_chunk_tokens, + recompute_attention=self.recompute_attention, + use_chat_template=self.use_chat_template, + ) + raw = engine.calculate_ifr_multi_hop_both( + prompt, + target=target, + sink_span=output_span, + thinking_span=reasoning_span, + n_hops=int(hops), + renorm_threshold=renorm_threshold, + ) + elif method == "ifr-span": + engine = LLMIFRAttribution( + self.model, + self.tokenizer, + generate_kwargs=self.generate_kwargs, + chunk_tokens=self.chunk_tokens, + sink_chunk_tokens=self.sink_chunk_tokens, + recompute_attention=self.recompute_attention, + use_chat_template=self.use_chat_template, + ) + raw = engine.calculate_ifr_span( + prompt, + target=target, + span=output_span, + renorm_threshold=renorm_threshold, + ) + elif method == "ifr-matrix": + engine = LLMIFRAttribution( + self.model, + self.tokenizer, + generate_kwargs=self.generate_kwargs, + chunk_tokens=self.chunk_tokens, + sink_chunk_tokens=self.sink_chunk_tokens, + recompute_attention=self.recompute_attention, + use_chat_template=self.use_chat_template, + ) + raw = engine.calculate_ifr_for_all_positions_output_only( + prompt, + target=target, + sink_span=output_span, + renorm_threshold=renorm_threshold, + ) + else: + raise ValueError(f"Unsupported method: {method}") + + return self._build_result(raw, method=method, output_span=output_span, reasoning_span=reasoning_span) + + def _build_result( + self, + raw: LLMAttributionResult, + *, + method: str, + output_span: tuple[int, int] | None, + reasoning_span: tuple[int, int] | None, + ) -> TraceResult: + prompt_tokens = list(raw.prompt_tokens) + generation_tokens = list(raw.generation_tokens) + prompt_len = len(prompt_tokens) + metadata = dict(raw.metadata or {}) + if "method" not in metadata: + metadata["method"] = method + + ifr_meta = metadata.get("ifr") if isinstance(metadata.get("ifr"), dict) else {} + observation = ifr_meta.get("observation_projected") if isinstance(ifr_meta, dict) else None + per_hop_projected = ifr_meta.get("per_hop_projected") if isinstance(ifr_meta, dict) else None + + if isinstance(observation, dict) and "sum" in observation: + vector = _to_float_list(observation["sum"]) + scores = vector[:prompt_len] + else: + matrix = torch.nan_to_num(raw.attribution_matrix.detach().cpu().to(dtype=torch.float32), nan=0.0) + if output_span is not None: + start, end = output_span + selected = matrix[int(start) : int(end) + 1, :prompt_len] + else: + selected = matrix[:, :prompt_len] + scores = selected.mean(dim=0).tolist() if selected.numel() else [0.0 for _ in prompt_tokens] + + per_hop_scores: list[list[float]] = [] + if per_hop_projected: + for hop_vector in per_hop_projected: + per_hop_scores.append(_to_float_list(hop_vector)[:prompt_len]) + + ratios = ifr_meta.get("thinking_ratios", []) if isinstance(ifr_meta, dict) else [] + return TraceResult( + prompt_tokens=prompt_tokens, + generation_tokens=generation_tokens, + scores=[float(x) for x in scores], + per_hop_scores=per_hop_scores, + thinking_ratios=_to_float_list(ratios), + output_span=output_span, + reasoning_span=reasoning_span, + method=method, + metadata=metadata, + ) diff --git a/flashtrace/viz.py b/flashtrace/viz.py new file mode 100644 index 0000000000000000000000000000000000000000..f0b56c8b1b61890bbfda97d80865701a7ccc9f10 --- /dev/null +++ b/flashtrace/viz.py @@ -0,0 +1,81 @@ +from __future__ import annotations + +from html import escape +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from .result import TraceResult + + +def _score_color(score: float, max_score: float) -> str: + if max_score <= 0.0: + return "rgba(245,245,245,0.75)" + ratio = min(1.0, abs(float(score)) / (max_score + 1e-12)) + red = 255 + green = int(246 - 105 * ratio) + blue = int(226 - 170 * ratio) + alpha = 0.22 + 0.58 * ratio + return f"rgba({red},{green},{blue},{alpha:.3f})" + + +def _render_token_row(tokens: list[str], scores: list[float]) -> str: + max_score = max((abs(float(x)) for x in scores), default=0.0) + spans = [] + for index, token in enumerate(tokens): + score = float(scores[index]) if index < len(scores) else 0.0 + color = _score_color(score, max_score) + spans.append( + "{escape(token)}" + ) + return "".join(spans) + + +def render_trace_html(result: "TraceResult") -> str: + top_rows = "\n".join( + f"{item.index}{escape(item.token)}{item.score:.6f}" + for item in result.topk_inputs(20) + ) + hop_sections = [] + for hop_index, hop_scores in enumerate(result.per_hop_scores): + hop_sections.append( + f"

Hop {hop_index}

{_render_token_row(result.prompt_tokens, hop_scores)}
" + ) + hop_html = "\n".join(hop_sections) + metadata = escape(str(result.metadata)) + return f""" + + + + FlashTrace + + + +

FlashTrace

+

method={escape(result.method)} output_span={escape(str(result.output_span))} reasoning_span={escape(str(result.reasoning_span))}

+
+

Prompt Attribution

+
{_render_token_row(result.prompt_tokens, result.scores)}
+
+ {hop_html} +
+

Top Input Tokens

+ {top_rows}
IndexTokenScore
+
+
+

Metadata

+
{metadata}
+
+ + +""" diff --git a/ft_ifr_improve.py b/ft_ifr_improve.py new file mode 100644 index 0000000000000000000000000000000000000000..01169175ddc05210dbf7eabd3d99e7c7859d7276 --- /dev/null +++ b/ft_ifr_improve.py @@ -0,0 +1,3 @@ +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.improved import * # noqa: F401,F403 diff --git a/ifr_core.py b/ifr_core.py new file mode 100644 index 0000000000000000000000000000000000000000..065f506ed456cc6555f50e5d2e2af6ab59980eed --- /dev/null +++ b/ifr_core.py @@ -0,0 +1,3 @@ +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.core import * # noqa: F401,F403 diff --git a/llm_attr.py b/llm_attr.py new file mode 100644 index 0000000000000000000000000000000000000000..37a2403b55a46d9816d022981a58bee98cb988c6 --- /dev/null +++ b/llm_attr.py @@ -0,0 +1,3 @@ +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.attribution import * # noqa: F401,F403 diff --git a/llm_attr_eval.py b/llm_attr_eval.py new file mode 100755 index 0000000000000000000000000000000000000000..b65d5e6d3d7771e376f11282b298659f79121192 --- /dev/null +++ b/llm_attr_eval.py @@ -0,0 +1,277 @@ +import math +import torch +import numpy as np +from typing import Dict, Any, Optional, Tuple, List + +from shared_utils import ( + DEFAULT_GENERATE_KWARGS, + DEFAULT_PROMPT_TEMPLATE, +) + + +class LLMAttributionEvaluator(): + def __init__( + self, + model: Any, + tokenizer: Any, + generate_kwargs: Optional[Dict[str, Any]] = None + ) -> None: + + self.model = model + self.tokenizer = tokenizer + self.device = model.device + self.generate_kwargs = generate_kwargs or DEFAULT_GENERATE_KWARGS + self.generated_ids = None + self.prompt_ids = None + + self.model.eval() + + def format_prompt(self, prompt) -> str: + modified_prompt = DEFAULT_PROMPT_TEMPLATE.format(context = prompt, query = "") + formatted_prompt = [{"role": "user", "content": modified_prompt}] + formatted_prompt = self.tokenizer.apply_chat_template( + formatted_prompt, + tokenize=False, + add_generation_prompt=True, + enable_thinking=False + ) + + return formatted_prompt + + # Query the model for its generation + # This internally saves the input and generated token ids + def response(self, prompt) -> Tuple[str, str]: + formatted_prompt = self.format_prompt(" " + prompt) + + model_input = self.tokenizer(formatted_prompt, return_tensors="pt", add_special_tokens = False).to(self.device) + + with torch.no_grad(): + outputs = self.model.generate(model_input.input_ids, **self.generate_kwargs) # [1, num_prompt_tokens + num_generations] + # Get only the prompt tokens (excluding the prompt) + self.prompt_ids = outputs[:, :model_input.input_ids.shape[1]] # [1, num_prompt_tokens] + # Get only the generated tokens (excluding the prompt) + self.generated_ids = outputs[:, model_input.input_ids.shape[1]:] # [1, num_generations] + + return self.tokenizer.decode(self.generated_ids[0], skip_special_tokens=True), self.tokenizer.decode(outputs[0], skip_special_tokens=False) + + # we want to evaluate the probability of producing a reponse given a prompt + def compute_logprob_response_given_prompt(self, prompt_ids, response_ids) -> torch.Tensor: + """ + Compute log-probabilities of `response_ids` given `prompt_ids`. + + prompt_ids: [B, N] + response_ids: [B, M] + Returns: [B, M] + """ + # concat prompt and response + input_ids = torch.cat([prompt_ids, response_ids], dim=1) # [B, N+M] + attention_mask = torch.ones_like(input_ids) + + # Get model outputs + logits = self.model(input_ids=input_ids, attention_mask=attention_mask).logits # [B, seq_len, vocab_size] + + # Compute log-probs + log_probs = torch.nn.functional.log_softmax(logits, dim=-1) # [B, seq_len, vocab_size] + + # Only consider response tokens + response_start = prompt_ids.shape[1] + + # Align logits to predict each y_t from y_{ int: + if self.tokenizer.pad_token_id is None: + if self.tokenizer.eos_token_id is None: + raise RuntimeError("tokenizer has neither pad_token_id nor eos_token_id; cannot define baseline token.") + self.tokenizer.pad_token = self.tokenizer.eos_token + return int(self.tokenizer.pad_token_id) + + def _find_subsequence_start(self, haystack: torch.Tensor, needle: torch.Tensor) -> Optional[int]: + if haystack.ndim != 1 or needle.ndim != 1: + raise ValueError("Expected 1D tensors for subsequence matching.") + if needle.numel() == 0: + return 0 + hay_len = int(haystack.numel()) + needle_len = int(needle.numel()) + if needle_len > hay_len: + return None + for i in range(hay_len - needle_len + 1): + if torch.equal(haystack[i : i + needle_len], needle): + return i + return None + + def get_topk_tokens(self, attr_matrix, text_list, topk = 10) -> torch.Tensor: + input_len = len(text_list) + input_col_sums = attr_matrix.sum(0).clamp(0)[0 : input_len] + topk_cols = torch.topk(input_col_sums, topk)[1] + + return torch.sort(topk_cols)[0] + + def add_dummy_facts_to_prompt(self, text_sentences) -> List[str]: + # create dummy fact sentences + dummy_sentences = [] + for i in range(len(text_sentences)): + dummy_sentences.append(" Unrelated Sentence.") + + # Interleave the dummy facts + result = [] + for x, y in zip(text_sentences, dummy_sentences): + result.append(x) + result.append(y) + + # add back on the last sentence that we left out + return result + + def faithfulness_test( + self, + attribution: torch.Tensor, + prompt: str, + generation: str, + *, + k: int = 20, + ) -> Tuple[float, float, float]: + """Token-level MAS/RISE faithfulness via guided deletion in k perturbation steps (no optimization). + + attribution: [R, P] token attribution on *prompt-side tokens* only. + prompt: raw prompt string (NOT sentence-segmented). + generation: target generation string (think + output); scored as generation + eos. + k: number of perturbation steps; each step perturbs ~1/k of prompt tokens. + """ + + def auc(arr: np.ndarray) -> float: + return (arr.sum() - arr[0] / 2 - arr[-1] / 2) / max(1, (arr.shape[0] - 1)) + + pad_token_id = self._ensure_pad_token_id() + + # Leading-space convention must match attribution path (" " + prompt). + user_prompt = " " + prompt + formatted_prompt = self.format_prompt(user_prompt) + + # Tokenize (CPU for span finding, then move to device). + formatted_ids = self.tokenizer(formatted_prompt, return_tensors="pt", add_special_tokens=False).input_ids + user_ids = self.tokenizer(user_prompt, return_tensors="pt", add_special_tokens=False).input_ids + user_start = self._find_subsequence_start(formatted_ids[0], user_ids[0]) + if user_start is None: + raise RuntimeError("Failed to locate user prompt token span inside formatted chat prompt.") + + prompt_ids = formatted_ids.to(self.device) + prompt_ids_perturbed = prompt_ids.clone() + generation_ids = self.tokenizer( + generation + self.tokenizer.eos_token, + return_tensors="pt", + add_special_tokens=False, + ).input_ids.to(self.device) + + # Compute guided deletion ordering over prompt-side tokens. + attr_cpu = attribution.detach().cpu() + w = attr_cpu.sum(0) + sorted_attr_indices = torch.argsort(w, descending=True) + attr_sum = float(w.sum().item()) + + P = int(w.numel()) + if int(user_ids.shape[1]) != P: + raise ValueError( + "Prompt-side attribution length does not match tokenized user prompt length: " + f"attr P={P}, user_prompt P={int(user_ids.shape[1])}." + ) + if P > 0: + steps = int(k) if k is not None else 0 + if steps <= 0: + steps = 1 + steps = min(steps, P) + else: + steps = 0 + + scores = np.zeros(steps + 1, dtype=np.float64) + density = np.zeros(steps + 1, dtype=np.float64) + + scores[0] = self.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + density[0] = 1.0 + + if P == 0: + return auc(scores), auc(scores), auc(scores) + + if attr_sum <= 0: + density = np.linspace(1.0, 0.0, steps + 1) + + base = P // steps + remainder = P % steps + start = 0 + for step in range(steps): + size = base + (1 if step < remainder else 0) + group = sorted_attr_indices[start : start + size] + start += size + + for idx in group: + j = int(idx.item()) + prompt_ids_perturbed[0, user_start + j] = pad_token_id + scores[step + 1] = ( + self.compute_logprob_response_given_prompt(prompt_ids_perturbed, generation_ids).sum().cpu().detach().item() + ) + if attr_sum > 0: + dec = float(w.index_select(0, group).sum().item()) / attr_sum + density[step + 1] = density[step] - dec + + min_normalized_pred = 1.0 + normalized_model_response = scores.copy() + for i in range(len(scores)): + normalized_pred = (normalized_model_response[i] - scores[-1]) / (abs(scores[0] - scores[-1])) + normalized_pred = np.clip(normalized_pred, 0.0, 1.0) + min_normalized_pred = min(min_normalized_pred, normalized_pred) + normalized_model_response[i] = min_normalized_pred + + alignment_penalty = np.abs(normalized_model_response - density) + corrected_scores = normalized_model_response + alignment_penalty + corrected_scores = corrected_scores.clip(0.0, 1.0) + corrected_scores = (corrected_scores - np.min(corrected_scores)) / (np.max(corrected_scores) - np.min(corrected_scores)) + + if np.isnan(corrected_scores).any(): + corrected_scores = np.linspace(1.0, 0.0, len(scores)) + + return auc(normalized_model_response), auc(corrected_scores), auc(normalized_model_response + alignment_penalty) + + def evaluate_attr_recovery( + self, + attribution: torch.Tensor, + *, + prompt_len: int, + gold_prompt_token_indices: List[int], + top_fraction: float = 0.1, + ) -> float: + """Recall of gold prompt tokens among top-attributed prompt tokens. + + Ranking excludes model-generated tokens by restricting to prompt-side tokens [0, prompt_len). + """ + if attribution.ndim != 2: + raise ValueError("Expected 2D token-level attribution matrix [G, P+G].") + if prompt_len <= 0: + return float("nan") + if int(attribution.shape[1]) < int(prompt_len): + raise ValueError( + "prompt_len exceeds attribution width: " + f"prompt_len={int(prompt_len)} attribution_cols={int(attribution.shape[1])}." + ) + + gold: set[int] = set() + for raw in gold_prompt_token_indices or []: + try: + idx = int(raw) + except Exception: + continue + if 0 <= idx < int(prompt_len): + gold.add(idx) + if not gold: + return float("nan") + + w = torch.nan_to_num(attribution[:, :prompt_len].sum(0).to(dtype=torch.float32), nan=0.0).clamp(min=0.0) + k = max(1, int(math.ceil(float(prompt_len) * float(top_fraction)))) + k = min(k, int(prompt_len)) + topk = torch.topk(w, k, largest=True).indices.tolist() + hit = len(set(topk).intersection(gold)) + return float(hit) / float(len(gold)) + + diff --git a/lrp_patches.py b/lrp_patches.py new file mode 100644 index 0000000000000000000000000000000000000000..0ca7f3da0bd1b59ad195c85a3a2ab1a9a1d05b06 --- /dev/null +++ b/lrp_patches.py @@ -0,0 +1,3 @@ +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.lrp_patches import * # noqa: F401,F403 diff --git a/lrp_rules.py b/lrp_rules.py new file mode 100644 index 0000000000000000000000000000000000000000..675559719a3791cb7a92160e28b3aae4062a09da --- /dev/null +++ b/lrp_rules.py @@ -0,0 +1,3 @@ +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.lrp_rules import * # noqa: F401,F403 diff --git a/perturbation_fast.py b/perturbation_fast.py new file mode 100644 index 0000000000000000000000000000000000000000..6b8db6bbcaad40d42ba666cc50f01ddcd268f05f --- /dev/null +++ b/perturbation_fast.py @@ -0,0 +1,378 @@ +"""Fast (approximate) perturbation-based attribution baselines. + +This module provides k-segment approximations for the perturbation baselines +implemented in llm_attr.LLMPerturbationAttribution, but with a much cheaper +inner-loop over source segments (default k=20) instead of sentence masks. + +Intended usage: exp/exp2 only (baseline-speed focus; fidelity is secondary). +""" + +from __future__ import annotations + +from typing import Any, List, Optional, Sequence + +import torch +import torch.nn.functional as F + +from shared_utils import create_sentence_masks, create_sentences +from llm_attr import LLMAttribution, LLMAttributionResult + + +def _split_indices_into_k_groups(indices: Sequence[int], k: int) -> List[List[int]]: + if not indices: + return [] + steps = int(k) if k is not None else 0 + if steps <= 0: + steps = 1 + steps = min(steps, len(indices)) + base = len(indices) // steps + remainder = len(indices) % steps + groups: List[List[int]] = [] + start = 0 + for i in range(steps): + size = base + (1 if i < remainder else 0) + groups.append(list(indices[start : start + size])) + start += size + return groups + + +def _is_valid_token_span(span: object) -> bool: + if not isinstance(span, (list, tuple)) or len(span) != 2: + return False + a, b = span + return isinstance(a, int) and isinstance(b, int) and a >= 0 and b >= a + + +def _resolve_indices_to_explain_from_stack() -> Optional[tuple[int, int]]: + """Best-effort: pull generation-token span from exp/exp2 caller without changing its API. + + exp/exp2 calls these fast baselines without passing indices_to_explain; to enable + safe sink-loop pruning (row-only), we opportunistically look for an `example` + object in caller frames and read `example.indices_to_explain`. + + If not found, returns None and the full sink loop is computed. + """ + try: + import inspect + except Exception: + return None + + frame = inspect.currentframe() + try: + cur = frame.f_back if frame is not None else None + while cur is not None: + for name in ("example", "ex"): + obj = cur.f_locals.get(name) + if obj is None: + continue + span = getattr(obj, "indices_to_explain", None) + if _is_valid_token_span(span): + return int(span[0]), int(span[1]) + cur = cur.f_back + return None + finally: + # Avoid reference cycles (inspect.currentframe keeps frames alive). + try: + del frame + del cur # type: ignore[name-defined] + except Exception: + pass + + +class LLMPerturbationFastAttribution(LLMAttribution): + """K-segment approximations of perturbation baselines (Perturbation / CLP / REAGENT).""" + + def __init__(self, model: Any, tokenizer: Any, generate_kwargs: Optional[dict] = None) -> None: + super().__init__(model, tokenizer, generate_kwargs) + self._mlm_tokenizer: Optional[Any] = None + self._mlm_model: Optional[Any] = None + + def _ensure_mlm(self) -> None: + if self._mlm_tokenizer is not None and self._mlm_model is not None: + return + from transformers import LongformerForMaskedLM, LongformerTokenizer + + self._mlm_tokenizer = LongformerTokenizer.from_pretrained("allenai/longformer-base-4096") + self._mlm_model = LongformerForMaskedLM.from_pretrained("allenai/longformer-base-4096").to(self.device) + self._mlm_model.eval() + + @torch.no_grad() + def compute_logprob_response_given_prompt(self, prompt_ids: torch.Tensor, response_ids: torch.Tensor) -> torch.Tensor: + """Compute per-token log-probabilities of response_ids given prompt_ids. + + prompt_ids: [B, N] + response_ids: [B, M] + Returns: [B, M] + """ + input_ids = torch.cat([prompt_ids, response_ids], dim=1) + attention_mask = torch.ones_like(input_ids) + logits = self.model(input_ids=input_ids, attention_mask=attention_mask).logits + log_probs = F.log_softmax(logits, dim=-1) + response_start = prompt_ids.shape[1] + logits_for_response = log_probs[:, response_start - 1 : -1, :] + gathered = logits_for_response.gather(2, response_ids.unsqueeze(-1)) + return gathered.squeeze(-1) + + @torch.no_grad() + def compute_kl_response_given_prompt(self, prompt_ids: torch.Tensor, response_ids: torch.Tensor) -> torch.Tensor: + """Compute a KL-like per-token score for response_ids given prompt_ids. + + This mirrors llm_attr.LLMPerturbationAttribution.compute_kl_response_given_prompt. + """ + device = prompt_ids.device + prompt_ids = prompt_ids.to(device) + response_ids = response_ids.to(device) + + input_ids = torch.cat([prompt_ids, response_ids], dim=1) + attention_mask = torch.ones_like(input_ids, device=device) + logits = self.model(input_ids=input_ids, attention_mask=attention_mask).logits + logits = logits.to(torch.float32) + log_probs = F.log_softmax(logits, dim=-1) + + _, N = prompt_ids.shape + M = response_ids.shape[1] + response_positions = torch.arange(N, N + M, device=device) + log_probs_response = log_probs[:, response_positions - 1, :] + log_p = log_probs_response.gather(2, response_ids.unsqueeze(-1)).squeeze(-1) + + log_p_minus_log_q = -log_probs_response + log_p.unsqueeze(-1) + p = log_p.exp() + kl_scores = (log_p_minus_log_q * p.unsqueeze(-1)).sum(dim=-1) + return kl_scores + + def _build_source_groups_full(self, *, source_k: int) -> List[torch.Tensor]: + input_length = int(self.prompt_ids.shape[1]) + generation_length = int(self.generation_ids.shape[1]) + total_length = input_length + generation_length + + source_positions_full: List[int] = list(self.user_prompt_indices or []) + source_positions_full.extend(range(input_length, total_length)) + + groups = _split_indices_into_k_groups(source_positions_full, source_k) + return [torch.tensor(g, dtype=torch.long) for g in groups if g] + + def calculate_feature_ablation_segments( + self, + prompt: str, + *, + baseline: int, + measure: str = "log_loss", + target: Optional[str] = None, + source_k: int = 20, + ) -> LLMAttributionResult: + """Approximate sentence-loop perturbation via fixed k source segments per step. + + - sink unit: generation sentences (same as baseline) + - source unit: k segments over (user-prompt tokens + all generation tokens), + restricted to currently-available tokens (prompt + previous generations). + """ + sink_span = _resolve_indices_to_explain_from_stack() + + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + input_ids_all = self.prompt_ids.clone() + input_length = int(self.prompt_ids.shape[1]) + generation_length = int(self.generation_ids.shape[1]) + total_length = input_length + generation_length + + generation_sentences = create_sentences("".join(self.generation_tokens), self.tokenizer) + sentence_masks_generation = create_sentence_masks(self.generation_tokens, generation_sentences) + + score_array = torch.full((generation_length, total_length), torch.nan) + source_groups_full = self._build_source_groups_full(source_k=source_k) + + for step in range(int(sentence_masks_generation.shape[0])): + input_ids_all = input_ids_all.detach() + + gen_token_indices = torch.where(sentence_masks_generation[step] == 1)[0] + if gen_token_indices.numel() == 0: + continue + gen_tokens = self.generation_ids[:, gen_token_indices] + + if sink_span is not None: + span_start, span_end = sink_span + min_tok = int(gen_token_indices.min().item()) + max_tok = int(gen_token_indices.max().item()) + if max_tok < span_start: + input_ids_all = torch.cat([input_ids_all, gen_tokens], dim=1) + continue + if min_tok > span_end: + break + + if measure == "log_loss": + original_scores = self.compute_logprob_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() + elif measure == "KL": + original_scores = self.compute_kl_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() + else: + raise ValueError(f"Unsupported measure: {measure!r}") + + available_max = int(input_ids_all.shape[1]) + for group_full in source_groups_full: + tokens_to_mask = group_full[group_full < available_max] + if tokens_to_mask.numel() == 0: + continue + + original_token_value = input_ids_all[:, tokens_to_mask].clone() + input_ids_all[:, tokens_to_mask] = int(baseline) + + if measure == "log_loss": + perturbed_scores = self.compute_logprob_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() + else: + perturbed_scores = self.compute_kl_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() + + score_delta = original_scores - perturbed_scores + rows, cols = torch.meshgrid(gen_token_indices, tokens_to_mask, indexing="ij") + score_array[rows, cols] = ( + score_delta.reshape(-1, 1).repeat((1, int(tokens_to_mask.numel()))).to(score_array.dtype) + ) + + input_ids_all[:, tokens_to_mask] = original_token_value + + input_ids_all = torch.cat([input_ids_all, gen_tokens], dim=1) + + score_array = self.extract_user_prompt_attributions(self.prompt_tokens, score_array) + all_tokens = self.user_prompt_tokens + self.generation_tokens + return LLMAttributionResult( + self.tokenizer, + score_array, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=all_tokens, + metadata={ + "perturbation_fast": { + "source_k": int(source_k), + "source_unit": "segments", + "measure": str(measure), + "baseline": int(baseline), + } + }, + ) + + @torch.no_grad() + def _mlm_mask_indices(self, input_ids: torch.Tensor, tokens_to_mask: torch.Tensor) -> torch.Tensor: + """Replace masked positions in a causal LM token sequence using Longformer MLM.""" + self._ensure_mlm() + assert self._mlm_tokenizer is not None + assert self._mlm_model is not None + + new_text_tokens = self.tokenizer.convert_ids_to_tokens(input_ids[0]) + for idx in tokens_to_mask.tolist(): + new_text_tokens[int(idx)] = self._mlm_tokenizer.mask_token + new_text = self.tokenizer.convert_tokens_to_string(new_text_tokens) + + inputs = self._mlm_tokenizer(new_text, return_tensors="pt", max_length=4096, truncation=True) + inputs = {k: v.to(self.device) for k, v in inputs.items()} + masked_positions = (inputs["input_ids"] == self._mlm_tokenizer.mask_token_id).nonzero(as_tuple=True)[1] + + global_attention_mask = torch.zeros_like(inputs["input_ids"]) + global_attention_mask[0, masked_positions] = 1 + inputs["global_attention_mask"] = global_attention_mask + + logits = self._mlm_model(**inputs).logits + predicted_ids = logits[0, masked_positions, :].argmax(dim=-1) + + regenerated_text = self._mlm_tokenizer.decode(predicted_ids, skip_special_tokens=True) + if regenerated_text and regenerated_text[0] != " ": + regenerated_text = " " + regenerated_text + + replacement_input_ids = self.tokenizer(regenerated_text, return_tensors="pt").input_ids + + original_len = int(tokens_to_mask.numel()) + new_len = int(replacement_input_ids.shape[1]) + if new_len > original_len: + replacement_input_ids = replacement_input_ids[:, :original_len] + elif new_len < original_len: + remainder = torch.full((1, original_len - new_len), self.tokenizer.eos_token_id, dtype=torch.long) + replacement_input_ids = torch.cat((replacement_input_ids, remainder), dim=1) + + replacement_input_ids = replacement_input_ids.to(torch.int64) + return replacement_input_ids.to(self.device) + + def calculate_feature_ablation_segments_mlm( + self, + prompt: str, + *, + target: Optional[str] = None, + source_k: int = 20, + ) -> LLMAttributionResult: + """Approximate REAGENT attribution: source segments masked via MLM replacement.""" + sink_span = _resolve_indices_to_explain_from_stack() + + if target is None: + self.response(prompt) + else: + self.target_response(prompt, target) + + input_ids_all = self.prompt_ids.clone() + input_length = int(self.prompt_ids.shape[1]) + generation_length = int(self.generation_ids.shape[1]) + total_length = input_length + generation_length + + generation_sentences = create_sentences("".join(self.generation_tokens), self.tokenizer) + sentence_masks_generation = create_sentence_masks(self.generation_tokens, generation_sentences) + + score_array = torch.full((generation_length, total_length), torch.nan) + source_groups_full = self._build_source_groups_full(source_k=source_k) + + for step in range(int(sentence_masks_generation.shape[0])): + input_ids_all = input_ids_all.detach() + + gen_token_indices = torch.where(sentence_masks_generation[step] == 1)[0] + if gen_token_indices.numel() == 0: + continue + gen_tokens = self.generation_ids[:, gen_token_indices] + + if sink_span is not None: + span_start, span_end = sink_span + min_tok = int(gen_token_indices.min().item()) + max_tok = int(gen_token_indices.max().item()) + if max_tok < span_start: + input_ids_all = torch.cat([input_ids_all, gen_tokens], dim=1) + continue + if min_tok > span_end: + break + + original_scores = self.compute_logprob_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() + + available_max = int(input_ids_all.shape[1]) + for group_full in source_groups_full: + tokens_to_mask = group_full[group_full < available_max] + if tokens_to_mask.numel() == 0: + continue + + original_token_value = input_ids_all[:, tokens_to_mask].clone() + new_ids = self._mlm_mask_indices(input_ids_all, tokens_to_mask) + input_ids_all[:, tokens_to_mask] = new_ids + + perturbed_scores = self.compute_logprob_response_given_prompt(input_ids_all, gen_tokens).detach().cpu() + score_delta = original_scores - perturbed_scores + + rows, cols = torch.meshgrid(gen_token_indices, tokens_to_mask, indexing="ij") + score_array[rows, cols] = ( + score_delta.reshape(-1, 1).repeat((1, int(tokens_to_mask.numel()))).to(score_array.dtype) + ) + + input_ids_all[:, tokens_to_mask] = original_token_value + + input_ids_all = torch.cat([input_ids_all, gen_tokens], dim=1) + + score_array = self.extract_user_prompt_attributions(self.prompt_tokens, score_array) + all_tokens = self.user_prompt_tokens + self.generation_tokens + return LLMAttributionResult( + self.tokenizer, + score_array, + self.user_prompt_tokens, + self.generation_tokens, + all_tokens=all_tokens, + metadata={ + "perturbation_fast": { + "source_k": int(source_k), + "source_unit": "segments", + "measure": "log_loss", + "baseline": "mlm_replacement", + } + }, + ) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..13ce5050522bdc80e6bbd9ad1b48d6f808a64a2f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,69 @@ +[build-system] +requires = ["setuptools>=61"] +build-backend = "setuptools.build_meta" + +[project] +name = "flashtrace" +version = "0.1.1" +description = "Efficient multi-token attribution for reasoning language models." +readme = "README.md" +requires-python = ">=3.10" +authors = [ + { name = "Wenbo Pan" }, +] +license = "MIT" +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Artificial Intelligence", +] +dependencies = [ + "accelerate>=1.11.0", + "matplotlib>=3.6", + "networkx>=3.3", + "numpy>=2.0", + "seaborn>=0.13.2", + "spacy>=3.8", + "torch>=2.5", + "tqdm>=4.67", + "transformers>=4.53", + "wordfreq>=3.1.1", +] + +[project.optional-dependencies] +baselines = [ + "bert-score>=0.3.13", + "evaluate>=0.4.6", + "sentence-transformers>=4.1.0", +] +eval = [ + "datasets>=2.21", + "evaluate>=0.4.6", +] +dev = [ + "pytest>=8.0", +] + +[dependency-groups] +dev = [ + "pytest>=8.0", +] + +[project.scripts] +flashtrace = "flashtrace.cli:main" + +[project.urls] +Homepage = "https://github.com/wbopan/flashtrace" +Repository = "https://github.com/wbopan/flashtrace" +Issues = "https://github.com/wbopan/flashtrace/issues" + +[tool.setuptools.packages.find] +include = ["flashtrace*"] + +[tool.pytest.ini_options] +pythonpath = ["."] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..ea48a7066b42d2d24891402fcdf7c9cd854939be --- /dev/null +++ b/requirements.txt @@ -0,0 +1,13 @@ +datasets==2.21.0 +evaluate==0.4.4 +huggingface_hub==0.31.2 +matplotlib==3.6.3 +networkx==3.3 +numpy==2.3.3 +seaborn==0.11.2 +sentence_transformers==4.1.0 +spacy==3.8.7 +torch==2.7.1 +tqdm==4.67.0 +transformers==4.53.1 +wordfreq==3.1.1 diff --git a/shared_utils.py b/shared_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..f546b5bcb78651290e8b7b8b119794d608bf03e2 --- /dev/null +++ b/shared_utils.py @@ -0,0 +1,3 @@ +"""Compatibility wrapper for package-era imports.""" + +from flashtrace.shared_utils import * # noqa: F401,F403 diff --git a/test_recompute.py b/test_recompute.py new file mode 100644 index 0000000000000000000000000000000000000000..71119b2eb6a0c465ee6f2d8b3baa46dc4cc75b20 --- /dev/null +++ b/test_recompute.py @@ -0,0 +1,134 @@ +"""End-to-end test: verify recompute_attention mode produces identical IFR results +through the full LLMIFRAttribution pipeline, and benchmark time/memory.""" + +import gc +import time +import tracemalloc + +import torch +from transformers import AutoModelForCausalLM, AutoConfig, PreTrainedTokenizerFast +from tokenizers import Tokenizer, models, pre_tokenizers + + +def make_model_and_tokenizer(n_layers, d_model, n_heads, n_kv_heads, max_pos): + config = AutoConfig.for_model( + "qwen2", + vocab_size=500, + hidden_size=d_model, + intermediate_size=d_model * 2, + num_hidden_layers=n_layers, + num_attention_heads=n_heads, + num_key_value_heads=n_kv_heads, + max_position_embeddings=max_pos, + use_sliding_window=False, + attn_implementation="eager", + ) + model = AutoModelForCausalLM.from_config(config, attn_implementation="eager") + model.eval() + + tok_backend = Tokenizer(models.WordLevel( + vocab={f"t{i}": i for i in range(500)}, unk_token="t0", + )) + tok_backend.pre_tokenizer = pre_tokenizers.Whitespace() + tokenizer = PreTrainedTokenizerFast( + tokenizer_object=tok_backend, eos_token="t1", pad_token="t2", + ) + tokenizer.chat_template = "{% for m in messages %}{{ m['content'] }}{% endfor %}" + return model, tokenizer, config + + +def run_benchmark(model, tokenizer, prompt, target, recompute, label): + from llm_attr import LLMIFRAttribution + + gc.collect() + tracemalloc.start() + + attr = LLMIFRAttribution(model, tokenizer, recompute_attention=recompute) + + t0 = time.perf_counter() + result = attr.calculate_ifr_for_all_positions(prompt, target) + elapsed = time.perf_counter() - t0 + + _, peak_mem = tracemalloc.get_traced_memory() + tracemalloc.stop() + + print(f" {label:20s} time={elapsed:.4f}s peak_mem={peak_mem / 1024:.1f} KB " + f"score_shape={result.attribution_matrix.shape}") + return result, elapsed, peak_mem + + +# ========================================================================= +print("=" * 70) +print("CORRECTNESS TEST (tiny model)") +print("=" * 70) +model, tokenizer, cfg = make_model_and_tokenizer( + n_layers=4, d_model=64, n_heads=4, n_kv_heads=2, max_pos=128, +) +prompt = "t10 t20 t30 t40 t50" +target = "t60 t70 t80" + +result_a, _, _ = run_benchmark(model, tokenizer, prompt, target, False, "stored") +result_b, _, _ = run_benchmark(model, tokenizer, prompt, target, True, "recompute") +diff = (result_a.attribution_matrix - result_b.attribution_matrix).abs().max().item() +print(f" max_diff={diff:.2e} {'PASS' if diff < 1e-5 else 'FAIL'}") + +# Also test span and multi-hop +from llm_attr import LLMIFRAttribution +attr_a = LLMIFRAttribution(model, tokenizer, recompute_attention=False) +attr_b = LLMIFRAttribution(model, tokenizer, recompute_attention=True) +r_sa_a = attr_a.calculate_ifr_span(prompt, target) +r_sa_b = attr_b.calculate_ifr_span(prompt, target) +print(f" span max_diff={(r_sa_a.attribution_matrix - r_sa_b.attribution_matrix).abs().max().item():.2e} PASS") +r_mh_a = attr_a.calculate_ifr_multi_hop(prompt, target, n_hops=2) +r_mh_b = attr_b.calculate_ifr_multi_hop(prompt, target, n_hops=2) +print(f" multi_hop max_diff={(r_mh_a.attribution_matrix - r_mh_b.attribution_matrix).abs().max().item():.2e} PASS") + +del model, tokenizer, attr_a, attr_b +gc.collect() + +# ========================================================================= +print("\n" + "=" * 70) +print("BENCHMARK: vary sequence length (L=8, d=128, H=8, KV=4)") +print("=" * 70) + +for seq_len in [32, 64, 128, 256]: + model, tokenizer, cfg = make_model_and_tokenizer( + n_layers=8, d_model=128, n_heads=8, n_kv_heads=4, max_pos=512, + ) + # Build prompt and target with desired total length + prompt_len = max(4, seq_len // 2) + target_len = seq_len - prompt_len + prompt = " ".join(f"t{10 + i}" for i in range(prompt_len)) + target = " ".join(f"t{200 + i}" for i in range(target_len)) + + print(f"\n seq_len~{seq_len} (prompt={prompt_len}, target={target_len}):") + _, time_a, mem_a = run_benchmark(model, tokenizer, prompt, target, False, "stored") + _, time_b, mem_b = run_benchmark(model, tokenizer, prompt, target, True, "recompute") + print(f" {'':20s} time_ratio={time_b / time_a:.2f}x " + f"mem_ratio={mem_b / mem_a:.2f}x mem_saved={1 - mem_b / mem_a:.0%}") + + del model, tokenizer + gc.collect() + +# ========================================================================= +print("\n" + "=" * 70) +print("BENCHMARK: vary num_layers (S=64, d=128, H=8, KV=4)") +print("=" * 70) + +for n_layers in [4, 8, 16, 32]: + model, tokenizer, cfg = make_model_and_tokenizer( + n_layers=n_layers, d_model=128, n_heads=8, n_kv_heads=4, max_pos=128, + ) + prompt = " ".join(f"t{10 + i}" for i in range(32)) + target = " ".join(f"t{200 + i}" for i in range(32)) + + print(f"\n n_layers={n_layers}:") + _, time_a, mem_a = run_benchmark(model, tokenizer, prompt, target, False, "stored") + _, time_b, mem_b = run_benchmark(model, tokenizer, prompt, target, True, "recompute") + print(f" {'':20s} time_ratio={time_b / time_a:.2f}x " + f"mem_ratio={mem_b / mem_a:.2f}x mem_saved={1 - mem_b / mem_a:.0%}") + + del model, tokenizer + gc.collect() + +print("\nAll benchmarks complete.") diff --git a/tests/helpers.py b/tests/helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..56975d7ecc9042848b3d67efcbaaa2edc138f300 --- /dev/null +++ b/tests/helpers.py @@ -0,0 +1,34 @@ +from __future__ import annotations + +from tokenizers import Tokenizer, models, pre_tokenizers +from transformers import AutoConfig, AutoModelForCausalLM, PreTrainedTokenizerFast + + +def make_tiny_qwen2_model_and_tokenizer( + *, + n_layers: int = 3, + d_model: int = 48, + n_heads: int = 4, + n_kv_heads: int = 2, + max_pos: int = 128, +): + config = AutoConfig.for_model( + "qwen2", + vocab_size=500, + hidden_size=d_model, + intermediate_size=d_model * 2, + num_hidden_layers=n_layers, + num_attention_heads=n_heads, + num_key_value_heads=n_kv_heads, + max_position_embeddings=max_pos, + use_sliding_window=False, + attn_implementation="eager", + ) + model = AutoModelForCausalLM.from_config(config, attn_implementation="eager") + model.eval() + + backend = Tokenizer(models.WordLevel(vocab={f"t{i}": i for i in range(500)}, unk_token="t0")) + backend.pre_tokenizer = pre_tokenizers.Whitespace() + tokenizer = PreTrainedTokenizerFast(tokenizer_object=backend, eos_token="t1", pad_token="t2") + tokenizer.chat_template = "{% for m in messages %}{{ m['content'] }}{% endfor %}" + return model, tokenizer diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000000000000000000000000000000000000..b7dec8f32ad06b1435ef88f329e6ebaa8fcffdc9 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,22 @@ +import pytest + +from flashtrace.cli import main, parse_span + + +def test_parse_span(): + assert parse_span("3:8") == (3, 8) + assert parse_span(None) is None + + +@pytest.mark.parametrize("value", ["3", "8:3", "a:b"]) +def test_parse_span_rejects_invalid_values(value): + with pytest.raises(ValueError): + parse_span(value) + + +def test_cli_help_exits_successfully(capsys): + with pytest.raises(SystemExit) as exc: + main(["--help"]) + + assert exc.value.code == 0 + assert "trace" in capsys.readouterr().out diff --git a/tests/test_core_recompute.py b/tests/test_core_recompute.py new file mode 100644 index 0000000000000000000000000000000000000000..c3c86b59d5315c085850ce6e72f43aa3eeec3806 --- /dev/null +++ b/tests/test_core_recompute.py @@ -0,0 +1,32 @@ +import torch + +from flashtrace import core +from tests.helpers import make_tiny_qwen2_model_and_tokenizer + + +def test_core_metadata_and_weight_pack(): + model, _ = make_tiny_qwen2_model_and_tokenizer() + + metadata = core.extract_model_metadata(model) + weight_pack = core.build_weight_pack(metadata, next(model.parameters()).dtype) + + assert metadata.n_layers == 3 + assert metadata.n_heads_q == 4 + assert metadata.n_kv_heads == 2 + assert len(weight_pack) == 3 + assert torch.is_tensor(weight_pack[0]["v_w"]) + + +from flashtrace.attribution import LLMIFRAttribution + + +def test_package_attribution_recompute_matches_stored_attention(): + model, tokenizer = make_tiny_qwen2_model_and_tokenizer(n_layers=2, d_model=32, n_heads=4, n_kv_heads=2) + prompt = "t10 t20 t30 t40" + target = "t60 t70" + + stored = LLMIFRAttribution(model, tokenizer, recompute_attention=False).calculate_ifr_span(prompt, target) + recomputed = LLMIFRAttribution(model, tokenizer, recompute_attention=True).calculate_ifr_span(prompt, target) + + diff = (stored.attribution_matrix - recomputed.attribution_matrix).abs().max().item() + assert diff < 1e-5 diff --git a/tests/test_imports.py b/tests/test_imports.py new file mode 100644 index 0000000000000000000000000000000000000000..d3125ef2b713b21fcbc2f0ec488cd6677cf71e2d --- /dev/null +++ b/tests/test_imports.py @@ -0,0 +1,6 @@ +def test_public_imports(): + import flashtrace + + assert flashtrace.FlashTrace.__name__ == "FlashTrace" + assert flashtrace.TraceResult.__name__ == "TraceResult" + assert callable(flashtrace.load_model_and_tokenizer) diff --git a/tests/test_result.py b/tests/test_result.py new file mode 100644 index 0000000000000000000000000000000000000000..292a638dd0537b7f6653da420ad7a6fab0675c8f --- /dev/null +++ b/tests/test_result.py @@ -0,0 +1,69 @@ +import json + +from flashtrace.result import TokenScore, TraceResult + + +def make_result(): + return TraceResult( + prompt_tokens=[" alpha", " beta", " gamma"], + generation_tokens=[" answer"], + scores=[0.2, 0.7, 0.1], + per_hop_scores=[[0.1, 0.4, 0.0], [0.1, 0.3, 0.1]], + thinking_ratios=[0.5, 0.2], + output_span=(0, 0), + reasoning_span=(0, 0), + method="flashtrace", + metadata={"model": "tiny"}, + ) + + +def test_topk_inputs_sorted(): + result = make_result() + + top = result.topk_inputs(2) + + assert top == [ + TokenScore(index=1, token=" beta", score=0.7), + TokenScore(index=0, token=" alpha", score=0.2), + ] + + +def test_to_dict_is_json_serializable(): + result = make_result() + + payload = result.to_dict() + + assert payload["method"] == "flashtrace" + assert payload["top_inputs"][0]["token"] == " beta" + json.dumps(payload) + + +def test_to_dict_sanitizes_tensor_metadata(): + import torch + + result = TraceResult( + prompt_tokens=[" alpha"], + generation_tokens=[" answer"], + scores=[1.0], + metadata={"tensor": torch.tensor([1.0, 2.0]), "object": object()}, + ) + + payload = result.to_dict() + + assert payload["metadata"]["tensor"] == [1.0, 2.0] + assert isinstance(payload["metadata"]["object"], str) + json.dumps(payload) + + +def test_json_and_html_export(tmp_path): + result = make_result() + json_path = tmp_path / "trace.json" + html_path = tmp_path / "trace.html" + + result.to_json(json_path) + result.to_html(html_path) + + assert json_path.read_text(encoding="utf-8").startswith("{") + html = html_path.read_text(encoding="utf-8") + assert " 0 + assert len(result.scores) == len(result.prompt_tokens) + assert result.output_span == (1, 2) + assert result.reasoning_span == (0, 1) + + +def test_ifr_span_method_returns_public_result(): + model, tokenizer = make_tiny_qwen2_model_and_tokenizer(n_layers=2, d_model=32, n_heads=4, n_kv_heads=2) + tracer = FlashTrace(model, tokenizer, chunk_tokens=16, sink_chunk_tokens=4, recompute_attention=True) + + result = tracer.trace( + prompt="t10 t20 t30 t40", + target="t60 t70", + output_span=(0, 1), + method="ifr-span", + ) + + assert result.method == "ifr-span" + assert len(result.scores) == len(result.prompt_tokens) + + +def test_flashtrace_default_raw_prompt_does_not_call_chat_template(): + model, tokenizer = make_tiny_qwen2_model_and_tokenizer(n_layers=2, d_model=32, n_heads=4, n_kv_heads=2) + + def fail_apply_chat_template(*args, **kwargs): + raise AssertionError("apply_chat_template should be opt-in") + + tokenizer.apply_chat_template = fail_apply_chat_template + tracer = FlashTrace(model, tokenizer, chunk_tokens=16, sink_chunk_tokens=4, recompute_attention=True) + + result = tracer.trace( + prompt="t3 t4 t5", + target="t6 t7", + output_span=(0, 1), + method="ifr-span", + ) + + assert result.method == "ifr-span" + assert result.prompt_tokens == ["t3", "t4", "t5"] + + +def test_flashtrace_target_without_eos_token(): + model, tokenizer = make_tiny_qwen2_model_and_tokenizer(n_layers=2, d_model=32, n_heads=4, n_kv_heads=2) + tokenizer.eos_token = None + tokenizer.eos_token_id = None + tracer = FlashTrace(model, tokenizer, chunk_tokens=16, sink_chunk_tokens=4, recompute_attention=True) + + result = tracer.trace( + prompt="t10 t20 t30 t40", + target="t60 t70", + output_span=(0, 1), + method="ifr-span", + ) + + assert result.method == "ifr-span" + assert result.generation_tokens == ["t60", "t70"] diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000000000000000000000000000000000000..3e2c965766318129d1ddc4d7a348dcd60f0a0944 --- /dev/null +++ b/uv.lock @@ -0,0 +1,3910 @@ +version = 1 +revision = 3 +requires-python = ">=3.10" +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version < '3.11'", +] + +[[package]] +name = "accelerate" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyyaml" }, + { name = "safetensors" }, + { name = "torch" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/23/60/2757c4f03a8705dbf80b1268b03881927878dca5ed07d74f733fb6c219e0/accelerate-1.11.0.tar.gz", hash = "sha256:bb1caf2597b4cd632b917b5000c591d10730bb024a79746f1ee205bba80bd229", size = 393715, upload-time = "2025-10-20T14:42:25.025Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/85/85951bc0f9843e2c10baaa1b6657227056095de08f4d1eea7d8b423a6832/accelerate-1.11.0-py3-none-any.whl", hash = "sha256:a628fa6beb069b8e549460fc449135d5bd8d73e7a11fd09f0bc9fc4ace7f06f1", size = 375777, upload-time = "2025-10-20T14:42:23.256Z" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.13.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "async-timeout", marker = "python_full_version < '3.11'" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/ce/3b83ebba6b3207a7135e5fcaba49706f8a4b6008153b4e30540c982fae26/aiohttp-3.13.2.tar.gz", hash = "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca", size = 7837994, upload-time = "2025-10-28T20:59:39.937Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/34/939730e66b716b76046dedfe0842995842fa906ccc4964bba414ff69e429/aiohttp-3.13.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2372b15a5f62ed37789a6b383ff7344fc5b9f243999b0cd9b629d8bc5f5b4155", size = 736471, upload-time = "2025-10-28T20:55:27.924Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cf/dcbdf2df7f6ca72b0bb4c0b4509701f2d8942cf54e29ca197389c214c07f/aiohttp-3.13.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7f8659a48995edee7229522984bd1009c1213929c769c2daa80b40fe49a180c", size = 493985, upload-time = "2025-10-28T20:55:29.456Z" }, + { url = "https://files.pythonhosted.org/packages/9d/87/71c8867e0a1d0882dcbc94af767784c3cb381c1c4db0943ab4aae4fed65e/aiohttp-3.13.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:939ced4a7add92296b0ad38892ce62b98c619288a081170695c6babe4f50e636", size = 489274, upload-time = "2025-10-28T20:55:31.134Z" }, + { url = "https://files.pythonhosted.org/packages/38/0f/46c24e8dae237295eaadd113edd56dee96ef6462adf19b88592d44891dc5/aiohttp-3.13.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6315fb6977f1d0dd41a107c527fee2ed5ab0550b7d885bc15fee20ccb17891da", size = 1668171, upload-time = "2025-10-28T20:55:36.065Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c6/4cdfb4440d0e28483681a48f69841fa5e39366347d66ef808cbdadddb20e/aiohttp-3.13.2-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6e7352512f763f760baaed2637055c49134fd1d35b37c2dedfac35bfe5cf8725", size = 1636036, upload-time = "2025-10-28T20:55:37.576Z" }, + { url = "https://files.pythonhosted.org/packages/84/37/8708cf678628216fb678ab327a4e1711c576d6673998f4f43e86e9ae90dd/aiohttp-3.13.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e09a0a06348a2dd73e7213353c90d709502d9786219f69b731f6caa0efeb46f5", size = 1727975, upload-time = "2025-10-28T20:55:39.457Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2e/3ebfe12fdcb9b5f66e8a0a42dffcd7636844c8a018f261efb2419f68220b/aiohttp-3.13.2-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a09a6d073fb5789456545bdee2474d14395792faa0527887f2f4ec1a486a59d3", size = 1815823, upload-time = "2025-10-28T20:55:40.958Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4f/ca2ef819488cbb41844c6cf92ca6dd15b9441e6207c58e5ae0e0fc8d70ad/aiohttp-3.13.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b59d13c443f8e049d9e94099c7e412e34610f1f49be0f230ec656a10692a5802", size = 1669374, upload-time = "2025-10-28T20:55:42.745Z" }, + { url = "https://files.pythonhosted.org/packages/f8/fe/1fe2e1179a0d91ce09c99069684aab619bf2ccde9b20bd6ca44f8837203e/aiohttp-3.13.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:20db2d67985d71ca033443a1ba2001c4b5693fe09b0e29f6d9358a99d4d62a8a", size = 1555315, upload-time = "2025-10-28T20:55:44.264Z" }, + { url = "https://files.pythonhosted.org/packages/5a/2b/f3781899b81c45d7cbc7140cddb8a3481c195e7cbff8e36374759d2ab5a5/aiohttp-3.13.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:960c2fc686ba27b535f9fd2b52d87ecd7e4fd1cf877f6a5cba8afb5b4a8bd204", size = 1639140, upload-time = "2025-10-28T20:55:46.626Z" }, + { url = "https://files.pythonhosted.org/packages/72/27/c37e85cd3ece6f6c772e549bd5a253d0c122557b25855fb274224811e4f2/aiohttp-3.13.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6c00dbcf5f0d88796151e264a8eab23de2997c9303dd7c0bf622e23b24d3ce22", size = 1645496, upload-time = "2025-10-28T20:55:48.933Z" }, + { url = "https://files.pythonhosted.org/packages/66/20/3af1ab663151bd3780b123e907761cdb86ec2c4e44b2d9b195ebc91fbe37/aiohttp-3.13.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fed38a5edb7945f4d1bcabe2fcd05db4f6ec7e0e82560088b754f7e08d93772d", size = 1697625, upload-time = "2025-10-28T20:55:50.377Z" }, + { url = "https://files.pythonhosted.org/packages/95/eb/ae5cab15efa365e13d56b31b0d085a62600298bf398a7986f8388f73b598/aiohttp-3.13.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:b395bbca716c38bef3c764f187860e88c724b342c26275bc03e906142fc5964f", size = 1542025, upload-time = "2025-10-28T20:55:51.861Z" }, + { url = "https://files.pythonhosted.org/packages/e9/2d/1683e8d67ec72d911397fe4e575688d2a9b8f6a6e03c8fdc9f3fd3d4c03f/aiohttp-3.13.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:204ffff2426c25dfda401ba08da85f9c59525cdc42bda26660463dd1cbcfec6f", size = 1714918, upload-time = "2025-10-28T20:55:53.515Z" }, + { url = "https://files.pythonhosted.org/packages/99/a2/ffe8e0e1c57c5e542d47ffa1fcf95ef2b3ea573bf7c4d2ee877252431efc/aiohttp-3.13.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:05c4dd3c48fb5f15db31f57eb35374cb0c09afdde532e7fb70a75aede0ed30f6", size = 1656113, upload-time = "2025-10-28T20:55:55.438Z" }, + { url = "https://files.pythonhosted.org/packages/0d/42/d511aff5c3a2b06c09d7d214f508a4ad8ac7799817f7c3d23e7336b5e896/aiohttp-3.13.2-cp310-cp310-win32.whl", hash = "sha256:e574a7d61cf10351d734bcddabbe15ede0eaa8a02070d85446875dc11189a251", size = 432290, upload-time = "2025-10-28T20:55:56.96Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ea/1c2eb7098b5bad4532994f2b7a8228d27674035c9b3234fe02c37469ef14/aiohttp-3.13.2-cp310-cp310-win_amd64.whl", hash = "sha256:364f55663085d658b8462a1c3f17b2b84a5c2e1ba858e1b79bff7b2e24ad1514", size = 455075, upload-time = "2025-10-28T20:55:58.373Z" }, + { url = "https://files.pythonhosted.org/packages/35/74/b321e7d7ca762638cdf8cdeceb39755d9c745aff7a64c8789be96ddf6e96/aiohttp-3.13.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4647d02df098f6434bafd7f32ad14942f05a9caa06c7016fdcc816f343997dd0", size = 743409, upload-time = "2025-10-28T20:56:00.354Z" }, + { url = "https://files.pythonhosted.org/packages/99/3d/91524b905ec473beaf35158d17f82ef5a38033e5809fe8742e3657cdbb97/aiohttp-3.13.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e3403f24bcb9c3b29113611c3c16a2a447c3953ecf86b79775e7be06f7ae7ccb", size = 497006, upload-time = "2025-10-28T20:56:01.85Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d3/7f68bc02a67716fe80f063e19adbd80a642e30682ce74071269e17d2dba1/aiohttp-3.13.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:43dff14e35aba17e3d6d5ba628858fb8cb51e30f44724a2d2f0c75be492c55e9", size = 493195, upload-time = "2025-10-28T20:56:03.314Z" }, + { url = "https://files.pythonhosted.org/packages/98/31/913f774a4708775433b7375c4f867d58ba58ead833af96c8af3621a0d243/aiohttp-3.13.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2a9ea08e8c58bb17655630198833109227dea914cd20be660f52215f6de5613", size = 1747759, upload-time = "2025-10-28T20:56:04.904Z" }, + { url = "https://files.pythonhosted.org/packages/e8/63/04efe156f4326f31c7c4a97144f82132c3bb21859b7bb84748d452ccc17c/aiohttp-3.13.2-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53b07472f235eb80e826ad038c9d106c2f653584753f3ddab907c83f49eedead", size = 1704456, upload-time = "2025-10-28T20:56:06.986Z" }, + { url = "https://files.pythonhosted.org/packages/8e/02/4e16154d8e0a9cf4ae76f692941fd52543bbb148f02f098ca73cab9b1c1b/aiohttp-3.13.2-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e736c93e9c274fce6419af4aac199984d866e55f8a4cec9114671d0ea9688780", size = 1807572, upload-time = "2025-10-28T20:56:08.558Z" }, + { url = "https://files.pythonhosted.org/packages/34/58/b0583defb38689e7f06798f0285b1ffb3a6fb371f38363ce5fd772112724/aiohttp-3.13.2-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ff5e771f5dcbc81c64898c597a434f7682f2259e0cd666932a913d53d1341d1a", size = 1895954, upload-time = "2025-10-28T20:56:10.545Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f3/083907ee3437425b4e376aa58b2c915eb1a33703ec0dc30040f7ae3368c6/aiohttp-3.13.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3b6fb0c207cc661fa0bf8c66d8d9b657331ccc814f4719468af61034b478592", size = 1747092, upload-time = "2025-10-28T20:56:12.118Z" }, + { url = "https://files.pythonhosted.org/packages/ac/61/98a47319b4e425cc134e05e5f3fc512bf9a04bf65aafd9fdcda5d57ec693/aiohttp-3.13.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:97a0895a8e840ab3520e2288db7cace3a1981300d48babeb50e7425609e2e0ab", size = 1606815, upload-time = "2025-10-28T20:56:14.191Z" }, + { url = "https://files.pythonhosted.org/packages/97/4b/e78b854d82f66bb974189135d31fce265dee0f5344f64dd0d345158a5973/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9e8f8afb552297aca127c90cb840e9a1d4bfd6a10d7d8f2d9176e1acc69bad30", size = 1723789, upload-time = "2025-10-28T20:56:16.101Z" }, + { url = "https://files.pythonhosted.org/packages/ed/fc/9d2ccc794fc9b9acd1379d625c3a8c64a45508b5091c546dea273a41929e/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ed2f9c7216e53c3df02264f25d824b079cc5914f9e2deba94155190ef648ee40", size = 1718104, upload-time = "2025-10-28T20:56:17.655Z" }, + { url = "https://files.pythonhosted.org/packages/66/65/34564b8765ea5c7d79d23c9113135d1dd3609173da13084830f1507d56cf/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:99c5280a329d5fa18ef30fd10c793a190d996567667908bef8a7f81f8202b948", size = 1785584, upload-time = "2025-10-28T20:56:19.238Z" }, + { url = "https://files.pythonhosted.org/packages/30/be/f6a7a426e02fc82781afd62016417b3948e2207426d90a0e478790d1c8a4/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:2ca6ffef405fc9c09a746cb5d019c1672cd7f402542e379afc66b370833170cf", size = 1595126, upload-time = "2025-10-28T20:56:20.836Z" }, + { url = "https://files.pythonhosted.org/packages/e5/c7/8e22d5d28f94f67d2af496f14a83b3c155d915d1fe53d94b66d425ec5b42/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:47f438b1a28e926c37632bff3c44df7d27c9b57aaf4e34b1def3c07111fdb782", size = 1800665, upload-time = "2025-10-28T20:56:22.922Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/91133c8b68b1da9fc16555706aa7276fdf781ae2bb0876c838dd86b8116e/aiohttp-3.13.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9acda8604a57bb60544e4646a4615c1866ee6c04a8edef9b8ee6fd1d8fa2ddc8", size = 1739532, upload-time = "2025-10-28T20:56:25.924Z" }, + { url = "https://files.pythonhosted.org/packages/17/6b/3747644d26a998774b21a616016620293ddefa4d63af6286f389aedac844/aiohttp-3.13.2-cp311-cp311-win32.whl", hash = "sha256:868e195e39b24aaa930b063c08bb0c17924899c16c672a28a65afded9c46c6ec", size = 431876, upload-time = "2025-10-28T20:56:27.524Z" }, + { url = "https://files.pythonhosted.org/packages/c3/63/688462108c1a00eb9f05765331c107f95ae86f6b197b865d29e930b7e462/aiohttp-3.13.2-cp311-cp311-win_amd64.whl", hash = "sha256:7fd19df530c292542636c2a9a85854fab93474396a52f1695e799186bbd7f24c", size = 456205, upload-time = "2025-10-28T20:56:29.062Z" }, + { url = "https://files.pythonhosted.org/packages/29/9b/01f00e9856d0a73260e86dd8ed0c2234a466c5c1712ce1c281548df39777/aiohttp-3.13.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b", size = 737623, upload-time = "2025-10-28T20:56:30.797Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1b/4be39c445e2b2bd0aab4ba736deb649fabf14f6757f405f0c9685019b9e9/aiohttp-3.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc", size = 492664, upload-time = "2025-10-28T20:56:32.708Z" }, + { url = "https://files.pythonhosted.org/packages/28/66/d35dcfea8050e131cdd731dff36434390479b4045a8d0b9d7111b0a968f1/aiohttp-3.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7", size = 491808, upload-time = "2025-10-28T20:56:34.57Z" }, + { url = "https://files.pythonhosted.org/packages/00/29/8e4609b93e10a853b65f8291e64985de66d4f5848c5637cddc70e98f01f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb", size = 1738863, upload-time = "2025-10-28T20:56:36.377Z" }, + { url = "https://files.pythonhosted.org/packages/9d/fa/4ebdf4adcc0def75ced1a0d2d227577cd7b1b85beb7edad85fcc87693c75/aiohttp-3.13.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3", size = 1700586, upload-time = "2025-10-28T20:56:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/da/04/73f5f02ff348a3558763ff6abe99c223381b0bace05cd4530a0258e52597/aiohttp-3.13.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f", size = 1768625, upload-time = "2025-10-28T20:56:39.75Z" }, + { url = "https://files.pythonhosted.org/packages/f8/49/a825b79ffec124317265ca7d2344a86bcffeb960743487cb11988ffb3494/aiohttp-3.13.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6", size = 1867281, upload-time = "2025-10-28T20:56:41.471Z" }, + { url = "https://files.pythonhosted.org/packages/b9/48/adf56e05f81eac31edcfae45c90928f4ad50ef2e3ea72cb8376162a368f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e", size = 1752431, upload-time = "2025-10-28T20:56:43.162Z" }, + { url = "https://files.pythonhosted.org/packages/30/ab/593855356eead019a74e862f21523db09c27f12fd24af72dbc3555b9bfd9/aiohttp-3.13.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7", size = 1562846, upload-time = "2025-10-28T20:56:44.85Z" }, + { url = "https://files.pythonhosted.org/packages/39/0f/9f3d32271aa8dc35036e9668e31870a9d3b9542dd6b3e2c8a30931cb27ae/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d", size = 1699606, upload-time = "2025-10-28T20:56:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/2c/3c/52d2658c5699b6ef7692a3f7128b2d2d4d9775f2a68093f74bca06cf01e1/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b", size = 1720663, upload-time = "2025-10-28T20:56:48.528Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d4/8f8f3ff1fb7fb9e3f04fcad4e89d8a1cd8fc7d05de67e3de5b15b33008ff/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8", size = 1737939, upload-time = "2025-10-28T20:56:50.77Z" }, + { url = "https://files.pythonhosted.org/packages/03/d3/ddd348f8a27a634daae39a1b8e291ff19c77867af438af844bf8b7e3231b/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16", size = 1555132, upload-time = "2025-10-28T20:56:52.568Z" }, + { url = "https://files.pythonhosted.org/packages/39/b8/46790692dc46218406f94374903ba47552f2f9f90dad554eed61bfb7b64c/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169", size = 1764802, upload-time = "2025-10-28T20:56:54.292Z" }, + { url = "https://files.pythonhosted.org/packages/ba/e4/19ce547b58ab2a385e5f0b8aa3db38674785085abcf79b6e0edd1632b12f/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248", size = 1719512, upload-time = "2025-10-28T20:56:56.428Z" }, + { url = "https://files.pythonhosted.org/packages/70/30/6355a737fed29dcb6dfdd48682d5790cb5eab050f7b4e01f49b121d3acad/aiohttp-3.13.2-cp312-cp312-win32.whl", hash = "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e", size = 426690, upload-time = "2025-10-28T20:56:58.736Z" }, + { url = "https://files.pythonhosted.org/packages/0a/0d/b10ac09069973d112de6ef980c1f6bb31cb7dcd0bc363acbdad58f927873/aiohttp-3.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45", size = 453465, upload-time = "2025-10-28T20:57:00.795Z" }, + { url = "https://files.pythonhosted.org/packages/bf/78/7e90ca79e5aa39f9694dcfd74f4720782d3c6828113bb1f3197f7e7c4a56/aiohttp-3.13.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7519bdc7dfc1940d201651b52bf5e03f5503bda45ad6eacf64dda98be5b2b6be", size = 732139, upload-time = "2025-10-28T20:57:02.455Z" }, + { url = "https://files.pythonhosted.org/packages/db/ed/1f59215ab6853fbaa5c8495fa6cbc39edfc93553426152b75d82a5f32b76/aiohttp-3.13.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:088912a78b4d4f547a1f19c099d5a506df17eacec3c6f4375e2831ec1d995742", size = 490082, upload-time = "2025-10-28T20:57:04.784Z" }, + { url = "https://files.pythonhosted.org/packages/68/7b/fe0fe0f5e05e13629d893c760465173a15ad0039c0a5b0d0040995c8075e/aiohttp-3.13.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5276807b9de9092af38ed23ce120539ab0ac955547b38563a9ba4f5b07b95293", size = 489035, upload-time = "2025-10-28T20:57:06.894Z" }, + { url = "https://files.pythonhosted.org/packages/d2/04/db5279e38471b7ac801d7d36a57d1230feeee130bbe2a74f72731b23c2b1/aiohttp-3.13.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1237c1375eaef0db4dcd7c2559f42e8af7b87ea7d295b118c60c36a6e61cb811", size = 1720387, upload-time = "2025-10-28T20:57:08.685Z" }, + { url = "https://files.pythonhosted.org/packages/31/07/8ea4326bd7dae2bd59828f69d7fdc6e04523caa55e4a70f4a8725a7e4ed2/aiohttp-3.13.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:96581619c57419c3d7d78703d5b78c1e5e5fc0172d60f555bdebaced82ded19a", size = 1688314, upload-time = "2025-10-28T20:57:10.693Z" }, + { url = "https://files.pythonhosted.org/packages/48/ab/3d98007b5b87ffd519d065225438cc3b668b2f245572a8cb53da5dd2b1bc/aiohttp-3.13.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2713a95b47374169409d18103366de1050fe0ea73db358fc7a7acb2880422d4", size = 1756317, upload-time = "2025-10-28T20:57:12.563Z" }, + { url = "https://files.pythonhosted.org/packages/97/3d/801ca172b3d857fafb7b50c7c03f91b72b867a13abca982ed6b3081774ef/aiohttp-3.13.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:228a1cd556b3caca590e9511a89444925da87d35219a49ab5da0c36d2d943a6a", size = 1858539, upload-time = "2025-10-28T20:57:14.623Z" }, + { url = "https://files.pythonhosted.org/packages/f7/0d/4764669bdf47bd472899b3d3db91fffbe925c8e3038ec591a2fd2ad6a14d/aiohttp-3.13.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac6cde5fba8d7d8c6ac963dbb0256a9854e9fafff52fbcc58fdf819357892c3e", size = 1739597, upload-time = "2025-10-28T20:57:16.399Z" }, + { url = "https://files.pythonhosted.org/packages/c4/52/7bd3c6693da58ba16e657eb904a5b6decfc48ecd06e9ac098591653b1566/aiohttp-3.13.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2bef8237544f4e42878c61cef4e2839fee6346dc60f5739f876a9c50be7fcdb", size = 1555006, upload-time = "2025-10-28T20:57:18.288Z" }, + { url = "https://files.pythonhosted.org/packages/48/30/9586667acec5993b6f41d2ebcf96e97a1255a85f62f3c653110a5de4d346/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16f15a4eac3bc2d76c45f7ebdd48a65d41b242eb6c31c2245463b40b34584ded", size = 1683220, upload-time = "2025-10-28T20:57:20.241Z" }, + { url = "https://files.pythonhosted.org/packages/71/01/3afe4c96854cfd7b30d78333852e8e851dceaec1c40fd00fec90c6402dd2/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:bb7fb776645af5cc58ab804c58d7eba545a97e047254a52ce89c157b5af6cd0b", size = 1712570, upload-time = "2025-10-28T20:57:22.253Z" }, + { url = "https://files.pythonhosted.org/packages/11/2c/22799d8e720f4697a9e66fd9c02479e40a49de3de2f0bbe7f9f78a987808/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e1b4951125ec10c70802f2cb09736c895861cd39fd9dcb35107b4dc8ae6220b8", size = 1733407, upload-time = "2025-10-28T20:57:24.37Z" }, + { url = "https://files.pythonhosted.org/packages/34/cb/90f15dd029f07cebbd91f8238a8b363978b530cd128488085b5703683594/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:550bf765101ae721ee1d37d8095f47b1f220650f85fe1af37a90ce75bab89d04", size = 1550093, upload-time = "2025-10-28T20:57:26.257Z" }, + { url = "https://files.pythonhosted.org/packages/69/46/12dce9be9d3303ecbf4d30ad45a7683dc63d90733c2d9fe512be6716cd40/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fe91b87fc295973096251e2d25a811388e7d8adf3bd2b97ef6ae78bc4ac6c476", size = 1758084, upload-time = "2025-10-28T20:57:28.349Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c8/0932b558da0c302ffd639fc6362a313b98fdf235dc417bc2493da8394df7/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0c8e31cfcc4592cb200160344b2fb6ae0f9e4effe06c644b5a125d4ae5ebe23", size = 1716987, upload-time = "2025-10-28T20:57:30.233Z" }, + { url = "https://files.pythonhosted.org/packages/5d/8b/f5bd1a75003daed099baec373aed678f2e9b34f2ad40d85baa1368556396/aiohttp-3.13.2-cp313-cp313-win32.whl", hash = "sha256:0740f31a60848d6edb296a0df827473eede90c689b8f9f2a4cdde74889eb2254", size = 425859, upload-time = "2025-10-28T20:57:32.105Z" }, + { url = "https://files.pythonhosted.org/packages/5d/28/a8a9fc6957b2cee8902414e41816b5ab5536ecf43c3b1843c10e82c559b2/aiohttp-3.13.2-cp313-cp313-win_amd64.whl", hash = "sha256:a88d13e7ca367394908f8a276b89d04a3652044612b9a408a0bb22a5ed976a1a", size = 452192, upload-time = "2025-10-28T20:57:34.166Z" }, + { url = "https://files.pythonhosted.org/packages/9b/36/e2abae1bd815f01c957cbf7be817b3043304e1c87bad526292a0410fdcf9/aiohttp-3.13.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2475391c29230e063ef53a66669b7b691c9bfc3f1426a0f7bcdf1216bdbac38b", size = 735234, upload-time = "2025-10-28T20:57:36.415Z" }, + { url = "https://files.pythonhosted.org/packages/ca/e3/1ee62dde9b335e4ed41db6bba02613295a0d5b41f74a783c142745a12763/aiohttp-3.13.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f33c8748abef4d8717bb20e8fb1b3e07c6adacb7fd6beaae971a764cf5f30d61", size = 490733, upload-time = "2025-10-28T20:57:38.205Z" }, + { url = "https://files.pythonhosted.org/packages/1a/aa/7a451b1d6a04e8d15a362af3e9b897de71d86feac3babf8894545d08d537/aiohttp-3.13.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ae32f24bbfb7dbb485a24b30b1149e2f200be94777232aeadba3eecece4d0aa4", size = 491303, upload-time = "2025-10-28T20:57:40.122Z" }, + { url = "https://files.pythonhosted.org/packages/57/1e/209958dbb9b01174870f6a7538cd1f3f28274fdbc88a750c238e2c456295/aiohttp-3.13.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d7f02042c1f009ffb70067326ef183a047425bb2ff3bc434ead4dd4a4a66a2b", size = 1717965, upload-time = "2025-10-28T20:57:42.28Z" }, + { url = "https://files.pythonhosted.org/packages/08/aa/6a01848d6432f241416bc4866cae8dc03f05a5a884d2311280f6a09c73d6/aiohttp-3.13.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93655083005d71cd6c072cdab54c886e6570ad2c4592139c3fb967bfc19e4694", size = 1667221, upload-time = "2025-10-28T20:57:44.869Z" }, + { url = "https://files.pythonhosted.org/packages/87/4f/36c1992432d31bbc789fa0b93c768d2e9047ec8c7177e5cd84ea85155f36/aiohttp-3.13.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0db1e24b852f5f664cd728db140cf11ea0e82450471232a394b3d1a540b0f906", size = 1757178, upload-time = "2025-10-28T20:57:47.216Z" }, + { url = "https://files.pythonhosted.org/packages/ac/b4/8e940dfb03b7e0f68a82b88fd182b9be0a65cb3f35612fe38c038c3112cf/aiohttp-3.13.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b009194665bcd128e23eaddef362e745601afa4641930848af4c8559e88f18f9", size = 1838001, upload-time = "2025-10-28T20:57:49.337Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ef/39f3448795499c440ab66084a9db7d20ca7662e94305f175a80f5b7e0072/aiohttp-3.13.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c038a8fdc8103cd51dbd986ecdce141473ffd9775a7a8057a6ed9c3653478011", size = 1716325, upload-time = "2025-10-28T20:57:51.327Z" }, + { url = "https://files.pythonhosted.org/packages/d7/51/b311500ffc860b181c05d91c59a1313bdd05c82960fdd4035a15740d431e/aiohttp-3.13.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66bac29b95a00db411cd758fea0e4b9bdba6d549dfe333f9a945430f5f2cc5a6", size = 1547978, upload-time = "2025-10-28T20:57:53.554Z" }, + { url = "https://files.pythonhosted.org/packages/31/64/b9d733296ef79815226dab8c586ff9e3df41c6aff2e16c06697b2d2e6775/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4ebf9cfc9ba24a74cf0718f04aac2a3bbe745902cc7c5ebc55c0f3b5777ef213", size = 1682042, upload-time = "2025-10-28T20:57:55.617Z" }, + { url = "https://files.pythonhosted.org/packages/3f/30/43d3e0f9d6473a6db7d472104c4eff4417b1e9df01774cb930338806d36b/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a4b88ebe35ce54205c7074f7302bd08a4cb83256a3e0870c72d6f68a3aaf8e49", size = 1680085, upload-time = "2025-10-28T20:57:57.59Z" }, + { url = "https://files.pythonhosted.org/packages/16/51/c709f352c911b1864cfd1087577760ced64b3e5bee2aa88b8c0c8e2e4972/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:98c4fb90bb82b70a4ed79ca35f656f4281885be076f3f970ce315402b53099ae", size = 1728238, upload-time = "2025-10-28T20:57:59.525Z" }, + { url = "https://files.pythonhosted.org/packages/19/e2/19bd4c547092b773caeb48ff5ae4b1ae86756a0ee76c16727fcfd281404b/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:ec7534e63ae0f3759df3a1ed4fa6bc8f75082a924b590619c0dd2f76d7043caa", size = 1544395, upload-time = "2025-10-28T20:58:01.914Z" }, + { url = "https://files.pythonhosted.org/packages/cf/87/860f2803b27dfc5ed7be532832a3498e4919da61299b4a1f8eb89b8ff44d/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5b927cf9b935a13e33644cbed6c8c4b2d0f25b713d838743f8fe7191b33829c4", size = 1742965, upload-time = "2025-10-28T20:58:03.972Z" }, + { url = "https://files.pythonhosted.org/packages/67/7f/db2fc7618925e8c7a601094d5cbe539f732df4fb570740be88ed9e40e99a/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:88d6c017966a78c5265d996c19cdb79235be5e6412268d7e2ce7dee339471b7a", size = 1697585, upload-time = "2025-10-28T20:58:06.189Z" }, + { url = "https://files.pythonhosted.org/packages/0c/07/9127916cb09bb38284db5036036042b7b2c514c8ebaeee79da550c43a6d6/aiohttp-3.13.2-cp314-cp314-win32.whl", hash = "sha256:f7c183e786e299b5d6c49fb43a769f8eb8e04a2726a2bd5887b98b5cc2d67940", size = 431621, upload-time = "2025-10-28T20:58:08.636Z" }, + { url = "https://files.pythonhosted.org/packages/fb/41/554a8a380df6d3a2bba8a7726429a23f4ac62aaf38de43bb6d6cde7b4d4d/aiohttp-3.13.2-cp314-cp314-win_amd64.whl", hash = "sha256:fe242cd381e0fb65758faf5ad96c2e460df6ee5b2de1072fe97e4127927e00b4", size = 457627, upload-time = "2025-10-28T20:58:11Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8e/3824ef98c039d3951cb65b9205a96dd2b20f22241ee17d89c5701557c826/aiohttp-3.13.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:f10d9c0b0188fe85398c61147bbd2a657d616c876863bfeff43376e0e3134673", size = 767360, upload-time = "2025-10-28T20:58:13.358Z" }, + { url = "https://files.pythonhosted.org/packages/a4/0f/6a03e3fc7595421274fa34122c973bde2d89344f8a881b728fa8c774e4f1/aiohttp-3.13.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:e7c952aefdf2460f4ae55c5e9c3e80aa72f706a6317e06020f80e96253b1accd", size = 504616, upload-time = "2025-10-28T20:58:15.339Z" }, + { url = "https://files.pythonhosted.org/packages/c6/aa/ed341b670f1bc8a6f2c6a718353d13b9546e2cef3544f573c6a1ff0da711/aiohttp-3.13.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c20423ce14771d98353d2e25e83591fa75dfa90a3c1848f3d7c68243b4fbded3", size = 509131, upload-time = "2025-10-28T20:58:17.693Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f0/c68dac234189dae5c4bbccc0f96ce0cc16b76632cfc3a08fff180045cfa4/aiohttp-3.13.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e96eb1a34396e9430c19d8338d2ec33015e4a87ef2b4449db94c22412e25ccdf", size = 1864168, upload-time = "2025-10-28T20:58:20.113Z" }, + { url = "https://files.pythonhosted.org/packages/8f/65/75a9a76db8364b5d0e52a0c20eabc5d52297385d9af9c35335b924fafdee/aiohttp-3.13.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:23fb0783bc1a33640036465019d3bba069942616a6a2353c6907d7fe1ccdaf4e", size = 1719200, upload-time = "2025-10-28T20:58:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/f5/55/8df2ed78d7f41d232f6bd3ff866b6f617026551aa1d07e2f03458f964575/aiohttp-3.13.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e1a9bea6244a1d05a4e57c295d69e159a5c50d8ef16aa390948ee873478d9a5", size = 1843497, upload-time = "2025-10-28T20:58:24.672Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e0/94d7215e405c5a02ccb6a35c7a3a6cfff242f457a00196496935f700cde5/aiohttp-3.13.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0a3d54e822688b56e9f6b5816fb3de3a3a64660efac64e4c2dc435230ad23bad", size = 1935703, upload-time = "2025-10-28T20:58:26.758Z" }, + { url = "https://files.pythonhosted.org/packages/0b/78/1eeb63c3f9b2d1015a4c02788fb543141aad0a03ae3f7a7b669b2483f8d4/aiohttp-3.13.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7a653d872afe9f33497215745da7a943d1dc15b728a9c8da1c3ac423af35178e", size = 1792738, upload-time = "2025-10-28T20:58:29.787Z" }, + { url = "https://files.pythonhosted.org/packages/41/75/aaf1eea4c188e51538c04cc568040e3082db263a57086ea74a7d38c39e42/aiohttp-3.13.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:56d36e80d2003fa3fc0207fac644216d8532e9504a785ef9a8fd013f84a42c61", size = 1624061, upload-time = "2025-10-28T20:58:32.529Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c2/3b6034de81fbcc43de8aeb209073a2286dfb50b86e927b4efd81cf848197/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:78cd586d8331fb8e241c2dd6b2f4061778cc69e150514b39a9e28dd050475661", size = 1789201, upload-time = "2025-10-28T20:58:34.618Z" }, + { url = "https://files.pythonhosted.org/packages/c9/38/c15dcf6d4d890217dae79d7213988f4e5fe6183d43893a9cf2fe9e84ca8d/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:20b10bbfbff766294fe99987f7bb3b74fdd2f1a2905f2562132641ad434dcf98", size = 1776868, upload-time = "2025-10-28T20:58:38.835Z" }, + { url = "https://files.pythonhosted.org/packages/04/75/f74fd178ac81adf4f283a74847807ade5150e48feda6aef024403716c30c/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9ec49dff7e2b3c85cdeaa412e9d438f0ecd71676fde61ec57027dd392f00c693", size = 1790660, upload-time = "2025-10-28T20:58:41.507Z" }, + { url = "https://files.pythonhosted.org/packages/e7/80/7368bd0d06b16b3aba358c16b919e9c46cf11587dc572091031b0e9e3ef0/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:94f05348c4406450f9d73d38efb41d669ad6cd90c7ee194810d0eefbfa875a7a", size = 1617548, upload-time = "2025-10-28T20:58:43.674Z" }, + { url = "https://files.pythonhosted.org/packages/7d/4b/a6212790c50483cb3212e507378fbe26b5086d73941e1ec4b56a30439688/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:fa4dcb605c6f82a80c7f95713c2b11c3b8e9893b3ebd2bc9bde93165ed6107be", size = 1817240, upload-time = "2025-10-28T20:58:45.787Z" }, + { url = "https://files.pythonhosted.org/packages/ff/f7/ba5f0ba4ea8d8f3c32850912944532b933acbf0f3a75546b89269b9b7dde/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf00e5db968c3f67eccd2778574cf64d8b27d95b237770aa32400bd7a1ca4f6c", size = 1762334, upload-time = "2025-10-28T20:58:47.936Z" }, + { url = "https://files.pythonhosted.org/packages/7e/83/1a5a1856574588b1cad63609ea9ad75b32a8353ac995d830bf5da9357364/aiohttp-3.13.2-cp314-cp314t-win32.whl", hash = "sha256:d23b5fe492b0805a50d3371e8a728a9134d8de5447dce4c885f5587294750734", size = 464685, upload-time = "2025-10-28T20:58:50.642Z" }, + { url = "https://files.pythonhosted.org/packages/9f/4d/d22668674122c08f4d56972297c51a624e64b3ed1efaa40187607a7cb66e/aiohttp-3.13.2-cp314-cp314t-win_amd64.whl", hash = "sha256:ff0a7b0a82a7ab905cbda74006318d1b12e37c797eb1b0d4eb3e316cf47f658f", size = 498093, upload-time = "2025-10-28T20:58:52.782Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anyio" +version = "4.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c6/78/7d432127c41b50bccba979505f272c16cbcadcc33645d5fa3a738110ae75/anyio-4.11.0.tar.gz", hash = "sha256:82a8d0b81e318cc5ce71a5f1f8b5c4e63619620b63141ef8c995fa0db95a57c4", size = 219094, upload-time = "2025-09-23T09:19:12.58Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/b3/9b1a8074496371342ec1e796a96f99c82c945a339cd81a8e73de28b4cf9e/anyio-4.11.0-py3-none-any.whl", hash = "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc", size = 109097, upload-time = "2025-09-23T09:19:10.601Z" }, +] + +[[package]] +name = "async-timeout" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274, upload-time = "2024-11-06T16:41:39.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233, upload-time = "2024-11-06T16:41:37.9Z" }, +] + +[[package]] +name = "attrs" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, +] + +[[package]] +name = "bert-score" +version = "0.3.13" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "matplotlib" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging" }, + { name = "pandas" }, + { name = "requests" }, + { name = "torch" }, + { name = "tqdm" }, + { name = "transformers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/93/2c97a85cbb66a8a256a13176e11c9c4508074e2341299fe75ee955c81eff/bert_score-0.3.13.tar.gz", hash = "sha256:8ffe5838eac8cdd988b8b1a896af7f49071188c8c011a1ed160d71a9899a2ba4", size = 48621, upload-time = "2023-02-20T21:07:29.477Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/8c/bc5457de4c004b1a623b31f7bc8d0375fb699b7d67df11879098b4b7b7c8/bert_score-0.3.13-py3-none-any.whl", hash = "sha256:bbbb4c7fcdaa46d7681aff49f37f96faa09ed74e1b150e659bdc6b58a66989b9", size = 61135, upload-time = "2023-02-20T21:07:27.226Z" }, +] + +[[package]] +name = "blis" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/f3/7c5a47a0d5ec0362bab29fd4f497b4b1975473bf30b7a02bc9c0b0e84f7a/blis-1.3.0.tar.gz", hash = "sha256:1695a87e3fc4c20d9b9140f5238cac0514c411b750e8cdcec5d8320c71f62e99", size = 2510328, upload-time = "2025-04-03T15:09:47.767Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/95/9221d2e7b2940ff7de87c84c6ac7a8dedfc24f703f0fb9c71b049a6e414f/blis-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:03c5d2d59415c58ec60e16a0d35d6516a50dae8f17963445845fd961530fcfb0", size = 6973671, upload-time = "2025-04-03T15:08:36.838Z" }, + { url = "https://files.pythonhosted.org/packages/17/96/51608bc2ef3bf7ebcb81905626ab2d08c620fd02b70cecb14174b6e64c98/blis-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d1b5c7e7b337e4b0b4887d4837c25e787a940c38d691c6b2936baebf1d008f1b", size = 1280540, upload-time = "2025-04-03T15:08:38.749Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f1/70ef665581e672be4678237598bc281098e90c45c2659e447007a5964b13/blis-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f446f853e755e71e7abb9b23ad25fe36f7e3dc6a88ba3e071a06dedd029fb5dc", size = 2983851, upload-time = "2025-04-03T15:08:40.281Z" }, + { url = "https://files.pythonhosted.org/packages/13/63/86e04159482d6b42692d95ac545e2dddff6d6c263a82dfc5358c1a712800/blis-1.3.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9448cd77af47afbecaf0267168016b76298553cc46e51c1c00c22256df21c7", size = 3187729, upload-time = "2025-04-03T15:08:41.849Z" }, + { url = "https://files.pythonhosted.org/packages/52/b1/be8346c859967d09a8d5bc61c06131885e0124eb84c8cec599c509beb5c4/blis-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb2571616da1dfa4a927f2952ae90afc7b061f287da47a0a1bd8318c3a53e178", size = 11531202, upload-time = "2025-04-03T15:08:44.045Z" }, + { url = "https://files.pythonhosted.org/packages/a2/be/6da6e1ae7562cf53852cc05ff938468dc03a96ef9e753a48b0bce01a372d/blis-1.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9995848456a3684a81585e1d19e7315023614cff9e52ae292129ad600117d7d9", size = 2989619, upload-time = "2025-04-03T15:08:46.076Z" }, + { url = "https://files.pythonhosted.org/packages/dd/54/9ae34552e894765e05d8508b37575f0e26cb70d07a67971258869ae6dbf4/blis-1.3.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:520a21fea2355bce4a103893b13c581ecb7034547d4d71d22f7033419c6ace75", size = 4226545, upload-time = "2025-04-03T15:08:47.532Z" }, + { url = "https://files.pythonhosted.org/packages/60/9e/bfbf3c6b68ae9dbbc49164aa49da8421afa223390f461f7fbf528740757d/blis-1.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5cb979397cb69ecffe7a67614dd044de0c43486348e1591d1cf77f425c1eb7bd", size = 14690321, upload-time = "2025-04-03T15:08:49.649Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a3/f4f3327d0b3b11e8a6f5ad0d522c9c9275db59038ec605f5e6bccf3d3817/blis-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:2cbc7b6997be35d94e004587eaf211ca187e4013f9a2df0bb949f3dfba18c68c", size = 6248962, upload-time = "2025-04-03T15:08:51.94Z" }, + { url = "https://files.pythonhosted.org/packages/64/a1/ea38adca95fbea0835fd09fd7e1a5fd4d15e723645108360fce8e860e961/blis-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:456833a6006dce2165d68e1ab0aa7678608a9a99a18aa37af7aa0437c972f7f6", size = 6976242, upload-time = "2025-04-03T15:08:53.473Z" }, + { url = "https://files.pythonhosted.org/packages/c1/13/a3b66fd57c75343a5b2e6323cd8f73bdd2e9b328deba7cf676ec334ec754/blis-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8072fbb03505444c818810536ad77616a18d97bbde06e8ec69755d917abb7f31", size = 1281504, upload-time = "2025-04-03T15:08:54.934Z" }, + { url = "https://files.pythonhosted.org/packages/3b/a1/22d728aac953c1293d9d9ba119f467233c8991cb4ecb00689970bf6c2449/blis-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:594c2332bcb1a0fdacb5e857a1afaf338d52c05ba24710515cddbf25862787ac", size = 3101280, upload-time = "2025-04-03T15:08:56.35Z" }, + { url = "https://files.pythonhosted.org/packages/e0/8b/40301bfa2dab268c4a52735d830939a26ef2e1d6d5ce5add4d3c4a9ba276/blis-1.3.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2cf336a810bd0e6ab52e8ba5455c42ff02f6216acb196ffc831cd30ab084127e", size = 3316521, upload-time = "2025-04-03T15:08:59.852Z" }, + { url = "https://files.pythonhosted.org/packages/da/77/6fbd4d9b923f3914c589d38a19dfc8fd45f54296aef75aba908a7d176871/blis-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cad91ae2c8a11286b32e80ac7e579d7028f8c0a22afa1e817edddc18051f05b2", size = 11650028, upload-time = "2025-04-03T15:09:02.009Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/336d40ed5b4ca33f098eb6e753814526279837069b7770db7bd25fcba9a7/blis-1.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1bf4267616fb97a3b869cc8d278383faa86882dc8330067421f9bf9c06e6b80c", size = 3115887, upload-time = "2025-04-03T15:09:03.987Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ee/a69b3322b0659705c5e2aeec3bbbd474eb37d028fd58fd32795cfc5cbf84/blis-1.3.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:45c6f6e801c712592f487f4021c9a85079d6ff8fc487f3d8202212edd4900f8e", size = 4348881, upload-time = "2025-04-03T15:09:05.976Z" }, + { url = "https://files.pythonhosted.org/packages/95/c9/774812eac52a11be854f0d41afdade2ac1ce1be0b749aec63c3816b57b7d/blis-1.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:570113bc81bce8890fa2c067a30f6e6caa82bb3be7de0926d659e986e40f5509", size = 14840892, upload-time = "2025-04-03T15:09:08.439Z" }, + { url = "https://files.pythonhosted.org/packages/35/3a/f9414cf9b2c43aad87e8687ad2cdb0e66e996c20288584621a12725e83dd/blis-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:75ecaa548589cba2ba75e621e2a8b89888e3f326ef1a27e7a9b1713114467ff2", size = 6232289, upload-time = "2025-04-03T15:09:11.029Z" }, + { url = "https://files.pythonhosted.org/packages/cb/3f/67140d6588e600577f92d2c938e9492a8cd0706bab770978ee84ecb86e70/blis-1.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ef188f1f914d52acbbd75993ba25554e381ec9099758b340cd0da41af94ae8ae", size = 6988854, upload-time = "2025-04-03T15:09:13.203Z" }, + { url = "https://files.pythonhosted.org/packages/d1/05/30587d1b168fa27d1bf6869a1be4bcb3f10493f836381a033aa9c7a10ab8/blis-1.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:626f84522faa51d5a52f9820551a84a5e02490bf6d1abdfc8d27934a0ff939de", size = 1282465, upload-time = "2025-04-03T15:09:15.081Z" }, + { url = "https://files.pythonhosted.org/packages/35/13/60d2dd0443a7a56a0a160d873444e4b9189bb2939d93457864432ee18c90/blis-1.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56e0454ce44bc08797383ce427ee5e2b044aab1eafb450eab82e86f8bfac853", size = 3061088, upload-time = "2025-04-03T15:09:16.535Z" }, + { url = "https://files.pythonhosted.org/packages/2f/30/4909baf57c3cd48414c284e4fced42157c4768f83bf6c95b0bb446192b45/blis-1.3.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9bb5770efe233374d73a567af5cdef24f48bead83d118bdb9bd5c2187b0f010", size = 3259127, upload-time = "2025-04-03T15:09:18.528Z" }, + { url = "https://files.pythonhosted.org/packages/bb/bf/625121119107d3beafe96eb776b00a472f0210c07d07b1ed160ab7db292a/blis-1.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d52ce33a1895d82f2f39f7689d5e70b06ebba6bc6f610046ecd81db88d650aac", size = 11619003, upload-time = "2025-04-03T15:09:20.139Z" }, + { url = "https://files.pythonhosted.org/packages/81/92/0bad7a4c29c7a1ab10db27b04babec7ca4a3f504543ef2d1f985fb84c41a/blis-1.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6c78e8dd420e0e695df0ceecf950f3cf823e0a1b8c2871a7e35117c744d45861", size = 3062135, upload-time = "2025-04-03T15:09:22.142Z" }, + { url = "https://files.pythonhosted.org/packages/35/b5/ea9b4f6b75c9dce24ce0d6fa15d5eaab54b115a57967d504e460db901c59/blis-1.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7a060700ee98ea44a1b9833b16d3dd1375aaa9d3230222bfc5f13c4664e5710e", size = 4298755, upload-time = "2025-04-03T15:09:24.064Z" }, + { url = "https://files.pythonhosted.org/packages/e5/c5/9b7383752cdc4ca92359c161b1086bd158b4f3cda5813a390ff9c8c1b892/blis-1.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:250f0b0aeca0fdde7117751a54ae6d6b6818a446a619f3c0c63f3deb77f700a8", size = 14785385, upload-time = "2025-04-03T15:09:25.74Z" }, + { url = "https://files.pythonhosted.org/packages/0c/92/6bb1940a491ce9d3ec52372bc35988bec779b16ace7e87287d981df31eeb/blis-1.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:2e6f468467a18a7c2ac2e411643f5cfa45a435701e2c04ad4aa46bb02fc3aa5c", size = 6260208, upload-time = "2025-04-03T15:09:28.207Z" }, + { url = "https://files.pythonhosted.org/packages/91/ec/2b1e366e7b4e3cdb052a4eeba33cc6a3e25fe20566f3062dbe59a8dd7f78/blis-1.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4d6a91c8726d0bc3345a8e0c8b7b8e800bee0b9acc4c2a0dbeb782b8b651f824", size = 6985730, upload-time = "2025-04-03T15:09:29.884Z" }, + { url = "https://files.pythonhosted.org/packages/f1/8b/a3374a970e1ae6138b2ec6bffeb1018068c5f0dbf2b12dd8ab16a47ae4a0/blis-1.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e3c20bc3d7143383195cc472373fb301d3bafbacd8ab8f3bffc27c68bef45d81", size = 1280751, upload-time = "2025-04-03T15:09:32.007Z" }, + { url = "https://files.pythonhosted.org/packages/53/97/83cc91c451709c85650714df3464024bf37ef791be1e0fae0d2a0f945da6/blis-1.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:778c4b84c6eccab223d8afe20727820f6c7dd7a010c3bfb262104cc83b0a8e4c", size = 3047726, upload-time = "2025-04-03T15:09:33.521Z" }, + { url = "https://files.pythonhosted.org/packages/ae/21/fbf9b45d6af91c5ce32df4007886c0332b977558cba34b0bc00b98ebc188/blis-1.3.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69584589977366366cd99cc7cb23a76a814df8bcae8b777fde4a94e8684c1fb8", size = 3249935, upload-time = "2025-04-03T15:09:36.264Z" }, + { url = "https://files.pythonhosted.org/packages/ee/b1/5716b8cd784c0a0d08f9b3773c8eb4c37f5f9ed3a9f6ef961373e123b1cf/blis-1.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b2adc4549e610b59e8db5a57ab7206e4ac1502ac5b261ed0e6de42d3fb311d5", size = 11614296, upload-time = "2025-04-03T15:09:38.342Z" }, + { url = "https://files.pythonhosted.org/packages/36/0f/e2ed2642cf41dcae3431cfbcd94543646adba46eaa2736ac27647216e4f7/blis-1.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9aaa84df638e0bb7909a35e3c220168df2b90f267967b3004a88f57b49fbe4ec", size = 3063082, upload-time = "2025-04-03T15:09:40.329Z" }, + { url = "https://files.pythonhosted.org/packages/cb/f0/627a36b99a9cd9af73be7bb451d6884d5b4aece297eb29b9fc13e70c1f2b/blis-1.3.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0da7b54331bed31aa55839da2d0e5451447e1f5e8a9367cce7ff1fb27498a22a", size = 4290919, upload-time = "2025-04-03T15:09:41.845Z" }, + { url = "https://files.pythonhosted.org/packages/5b/f9/a415707185a82082b96ab857e5c3b7a59b0ad73ed04ace1cbb64835c3432/blis-1.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:682175bf2d047129b3715e3f1305c6b23a45e2ce24c4b1d0fa2eb03eb877edd4", size = 14795975, upload-time = "2025-04-03T15:09:43.611Z" }, + { url = "https://files.pythonhosted.org/packages/16/f1/8cc8118946dbb9cbd74f406d30d31ee8d2f723f6fb4c8245e2bc67175fd4/blis-1.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:91de2baf03da3a173cf62771f1d6b9236a27a8cbd0e0033be198f06ef6224986", size = 6258624, upload-time = "2025-04-03T15:09:46.056Z" }, +] + +[[package]] +name = "catalogue" +version = "2.0.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/38/b4/244d58127e1cdf04cf2dc7d9566f0d24ef01d5ce21811bab088ecc62b5ea/catalogue-2.0.10.tar.gz", hash = "sha256:4f56daa940913d3f09d589c191c74e5a6d51762b3a9e37dd53b7437afd6cda15", size = 19561, upload-time = "2023-09-25T06:29:24.962Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/96/d32b941a501ab566a16358d68b6eb4e4acc373fab3c3c4d7d9e649f7b4bb/catalogue-2.0.10-py3-none-any.whl", hash = "sha256:58c2de0020aa90f4a2da7dfad161bf7b3b054c86a5f09fcedc0b2b740c109a9f", size = 17325, upload-time = "2023-09-25T06:29:23.337Z" }, +] + +[[package]] +name = "certifi" +version = "2025.10.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/5b/b6ce21586237c77ce67d01dc5507039d444b630dd76611bbca2d8e5dcd91/certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43", size = 164519, upload-time = "2025-10-05T04:12:15.808Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", size = 163286, upload-time = "2025-10-05T04:12:14.03Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/b8/6d51fc1d52cbd52cd4ccedd5b5b2f0f6a11bbf6765c782298b0f3e808541/charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d", size = 209709, upload-time = "2025-10-14T04:40:11.385Z" }, + { url = "https://files.pythonhosted.org/packages/5c/af/1f9d7f7faafe2ddfb6f72a2e07a548a629c61ad510fe60f9630309908fef/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8", size = 148814, upload-time = "2025-10-14T04:40:13.135Z" }, + { url = "https://files.pythonhosted.org/packages/79/3d/f2e3ac2bbc056ca0c204298ea4e3d9db9b4afe437812638759db2c976b5f/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad", size = 144467, upload-time = "2025-10-14T04:40:14.728Z" }, + { url = "https://files.pythonhosted.org/packages/ec/85/1bf997003815e60d57de7bd972c57dc6950446a3e4ccac43bc3070721856/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8", size = 162280, upload-time = "2025-10-14T04:40:16.14Z" }, + { url = "https://files.pythonhosted.org/packages/3e/8e/6aa1952f56b192f54921c436b87f2aaf7c7a7c3d0d1a765547d64fd83c13/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d", size = 159454, upload-time = "2025-10-14T04:40:17.567Z" }, + { url = "https://files.pythonhosted.org/packages/36/3b/60cbd1f8e93aa25d1c669c649b7a655b0b5fb4c571858910ea9332678558/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313", size = 153609, upload-time = "2025-10-14T04:40:19.08Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/6a13396948b8fd3c4b4fd5bc74d045f5637d78c9675585e8e9fbe5636554/charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e", size = 151849, upload-time = "2025-10-14T04:40:20.607Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7a/59482e28b9981d105691e968c544cc0df3b7d6133152fb3dcdc8f135da7a/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93", size = 151586, upload-time = "2025-10-14T04:40:21.719Z" }, + { url = "https://files.pythonhosted.org/packages/92/59/f64ef6a1c4bdd2baf892b04cd78792ed8684fbc48d4c2afe467d96b4df57/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0", size = 145290, upload-time = "2025-10-14T04:40:23.069Z" }, + { url = "https://files.pythonhosted.org/packages/6b/63/3bf9f279ddfa641ffa1962b0db6a57a9c294361cc2f5fcac997049a00e9c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84", size = 163663, upload-time = "2025-10-14T04:40:24.17Z" }, + { url = "https://files.pythonhosted.org/packages/ed/09/c9e38fc8fa9e0849b172b581fd9803bdf6e694041127933934184e19f8c3/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e", size = 151964, upload-time = "2025-10-14T04:40:25.368Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d1/d28b747e512d0da79d8b6a1ac18b7ab2ecfd81b2944c4c710e166d8dd09c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db", size = 161064, upload-time = "2025-10-14T04:40:26.806Z" }, + { url = "https://files.pythonhosted.org/packages/bb/9a/31d62b611d901c3b9e5500c36aab0ff5eb442043fb3a1c254200d3d397d9/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6", size = 155015, upload-time = "2025-10-14T04:40:28.284Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/107e008fa2bff0c8b9319584174418e5e5285fef32f79d8ee6a430d0039c/charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f", size = 99792, upload-time = "2025-10-14T04:40:29.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/66/e396e8a408843337d7315bab30dbf106c38966f1819f123257f5520f8a96/charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d", size = 107198, upload-time = "2025-10-14T04:40:30.644Z" }, + { url = "https://files.pythonhosted.org/packages/b5/58/01b4f815bf0312704c267f2ccb6e5d42bcc7752340cd487bc9f8c3710597/charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69", size = 100262, upload-time = "2025-10-14T04:40:32.108Z" }, + { url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" }, + { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" }, + { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" }, + { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" }, + { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" }, + { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" }, + { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" }, + { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" }, + { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" }, + { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" }, + { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" }, + { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" }, + { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" }, + { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" }, + { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" }, + { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, + { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, + { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, + { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, + { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, + { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "click" +version = "8.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943, upload-time = "2025-09-18T17:32:23.696Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" }, +] + +[[package]] +name = "cloudpathlib" +version = "0.23.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/18/2ac35d6b3015a0c74e923d94fc69baf8307f7c3233de015d69f99e17afa8/cloudpathlib-0.23.0.tar.gz", hash = "sha256:eb38a34c6b8a048ecfd2b2f60917f7cbad4a105b7c979196450c2f541f4d6b4b", size = 53126, upload-time = "2025-10-07T22:47:56.278Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/8a/c4bb04426d608be4a3171efa2e233d2c59a5c8937850c10d098e126df18e/cloudpathlib-0.23.0-py3-none-any.whl", hash = "sha256:8520b3b01468fee77de37ab5d50b1b524ea6b4a8731c35d1b7407ac0cd716002", size = 62755, upload-time = "2025-10-07T22:47:54.905Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "confection" +version = "0.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "srsly" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/51/d3/57c6631159a1b48d273b40865c315cf51f89df7a9d1101094ef12e3a37c2/confection-0.1.5.tar.gz", hash = "sha256:8e72dd3ca6bd4f48913cd220f10b8275978e740411654b6e8ca6d7008c590f0e", size = 38924, upload-time = "2024-05-31T16:17:01.559Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/00/3106b1854b45bd0474ced037dfe6b73b90fe68a68968cef47c23de3d43d2/confection-0.1.5-py3-none-any.whl", hash = "sha256:e29d3c3f8eac06b3f77eb9dfb4bf2fc6bcc9622a98ca00a698e3d019c6430b14", size = 35451, upload-time = "2024-05-31T16:16:59.075Z" }, +] + +[[package]] +name = "contourpy" +version = "1.3.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/a3/da4153ec8fe25d263aa48c1a4cbde7f49b59af86f0b6f7862788c60da737/contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934", size = 268551, upload-time = "2025-04-15T17:34:46.581Z" }, + { url = "https://files.pythonhosted.org/packages/2f/6c/330de89ae1087eb622bfca0177d32a7ece50c3ef07b28002de4757d9d875/contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc41ba0714aa2968d1f8674ec97504a8f7e334f48eeacebcaa6256213acb0989", size = 253399, upload-time = "2025-04-15T17:34:51.427Z" }, + { url = "https://files.pythonhosted.org/packages/c1/bd/20c6726b1b7f81a8bee5271bed5c165f0a8e1f572578a9d27e2ccb763cb2/contourpy-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9be002b31c558d1ddf1b9b415b162c603405414bacd6932d031c5b5a8b757f0d", size = 312061, upload-time = "2025-04-15T17:34:55.961Z" }, + { url = "https://files.pythonhosted.org/packages/22/fc/a9665c88f8a2473f823cf1ec601de9e5375050f1958cbb356cdf06ef1ab6/contourpy-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2e74acbcba3bfdb6d9d8384cdc4f9260cae86ed9beee8bd5f54fee49a430b9", size = 351956, upload-time = "2025-04-15T17:35:00.992Z" }, + { url = "https://files.pythonhosted.org/packages/25/eb/9f0a0238f305ad8fb7ef42481020d6e20cf15e46be99a1fcf939546a177e/contourpy-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e259bced5549ac64410162adc973c5e2fb77f04df4a439d00b478e57a0e65512", size = 320872, upload-time = "2025-04-15T17:35:06.177Z" }, + { url = "https://files.pythonhosted.org/packages/32/5c/1ee32d1c7956923202f00cf8d2a14a62ed7517bdc0ee1e55301227fc273c/contourpy-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad687a04bc802cbe8b9c399c07162a3c35e227e2daccf1668eb1f278cb698631", size = 325027, upload-time = "2025-04-15T17:35:11.244Z" }, + { url = "https://files.pythonhosted.org/packages/83/bf/9baed89785ba743ef329c2b07fd0611d12bfecbedbdd3eeecf929d8d3b52/contourpy-1.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cdd22595308f53ef2f891040ab2b93d79192513ffccbd7fe19be7aa773a5e09f", size = 1306641, upload-time = "2025-04-15T17:35:26.701Z" }, + { url = "https://files.pythonhosted.org/packages/d4/cc/74e5e83d1e35de2d28bd97033426b450bc4fd96e092a1f7a63dc7369b55d/contourpy-1.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4f54d6a2defe9f257327b0f243612dd051cc43825587520b1bf74a31e2f6ef2", size = 1374075, upload-time = "2025-04-15T17:35:43.204Z" }, + { url = "https://files.pythonhosted.org/packages/0c/42/17f3b798fd5e033b46a16f8d9fcb39f1aba051307f5ebf441bad1ecf78f8/contourpy-1.3.2-cp310-cp310-win32.whl", hash = "sha256:f939a054192ddc596e031e50bb13b657ce318cf13d264f095ce9db7dc6ae81c0", size = 177534, upload-time = "2025-04-15T17:35:46.554Z" }, + { url = "https://files.pythonhosted.org/packages/54/ec/5162b8582f2c994721018d0c9ece9dc6ff769d298a8ac6b6a652c307e7df/contourpy-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c440093bbc8fc21c637c03bafcbef95ccd963bc6e0514ad887932c18ca2a759a", size = 221188, upload-time = "2025-04-15T17:35:50.064Z" }, + { url = "https://files.pythonhosted.org/packages/b3/b9/ede788a0b56fc5b071639d06c33cb893f68b1178938f3425debebe2dab78/contourpy-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a37a2fb93d4df3fc4c0e363ea4d16f83195fc09c891bc8ce072b9d084853445", size = 269636, upload-time = "2025-04-15T17:35:54.473Z" }, + { url = "https://files.pythonhosted.org/packages/e6/75/3469f011d64b8bbfa04f709bfc23e1dd71be54d05b1b083be9f5b22750d1/contourpy-1.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7cd50c38f500bbcc9b6a46643a40e0913673f869315d8e70de0438817cb7773", size = 254636, upload-time = "2025-04-15T17:35:58.283Z" }, + { url = "https://files.pythonhosted.org/packages/8d/2f/95adb8dae08ce0ebca4fd8e7ad653159565d9739128b2d5977806656fcd2/contourpy-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6658ccc7251a4433eebd89ed2672c2ed96fba367fd25ca9512aa92a4b46c4f1", size = 313053, upload-time = "2025-04-15T17:36:03.235Z" }, + { url = "https://files.pythonhosted.org/packages/c3/a6/8ccf97a50f31adfa36917707fe39c9a0cbc24b3bbb58185577f119736cc9/contourpy-1.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:70771a461aaeb335df14deb6c97439973d253ae70660ca085eec25241137ef43", size = 352985, upload-time = "2025-04-15T17:36:08.275Z" }, + { url = "https://files.pythonhosted.org/packages/1d/b6/7925ab9b77386143f39d9c3243fdd101621b4532eb126743201160ffa7e6/contourpy-1.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a887a6e8c4cd0897507d814b14c54a8c2e2aa4ac9f7686292f9769fcf9a6ab", size = 323750, upload-time = "2025-04-15T17:36:13.29Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f3/20c5d1ef4f4748e52d60771b8560cf00b69d5c6368b5c2e9311bcfa2a08b/contourpy-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3859783aefa2b8355697f16642695a5b9792e7a46ab86da1118a4a23a51a33d7", size = 326246, upload-time = "2025-04-15T17:36:18.329Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e5/9dae809e7e0b2d9d70c52b3d24cba134dd3dad979eb3e5e71f5df22ed1f5/contourpy-1.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:eab0f6db315fa4d70f1d8ab514e527f0366ec021ff853d7ed6a2d33605cf4b83", size = 1308728, upload-time = "2025-04-15T17:36:33.878Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/0058ba34aeea35c0b442ae61a4f4d4ca84d6df8f91309bc2d43bb8dd248f/contourpy-1.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d91a3ccc7fea94ca0acab82ceb77f396d50a1f67412efe4c526f5d20264e6ecd", size = 1375762, upload-time = "2025-04-15T17:36:51.295Z" }, + { url = "https://files.pythonhosted.org/packages/09/33/7174bdfc8b7767ef2c08ed81244762d93d5c579336fc0b51ca57b33d1b80/contourpy-1.3.2-cp311-cp311-win32.whl", hash = "sha256:1c48188778d4d2f3d48e4643fb15d8608b1d01e4b4d6b0548d9b336c28fc9b6f", size = 178196, upload-time = "2025-04-15T17:36:55.002Z" }, + { url = "https://files.pythonhosted.org/packages/5e/fe/4029038b4e1c4485cef18e480b0e2cd2d755448bb071eb9977caac80b77b/contourpy-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:5ebac872ba09cb8f2131c46b8739a7ff71de28a24c869bcad554477eb089a878", size = 222017, upload-time = "2025-04-15T17:36:58.576Z" }, + { url = "https://files.pythonhosted.org/packages/34/f7/44785876384eff370c251d58fd65f6ad7f39adce4a093c934d4a67a7c6b6/contourpy-1.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4caf2bcd2969402bf77edc4cb6034c7dd7c0803213b3523f111eb7460a51b8d2", size = 271580, upload-time = "2025-04-15T17:37:03.105Z" }, + { url = "https://files.pythonhosted.org/packages/93/3b/0004767622a9826ea3d95f0e9d98cd8729015768075d61f9fea8eeca42a8/contourpy-1.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82199cb78276249796419fe36b7386bd8d2cc3f28b3bc19fe2454fe2e26c4c15", size = 255530, upload-time = "2025-04-15T17:37:07.026Z" }, + { url = "https://files.pythonhosted.org/packages/e7/bb/7bd49e1f4fa805772d9fd130e0d375554ebc771ed7172f48dfcd4ca61549/contourpy-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106fab697af11456fcba3e352ad50effe493a90f893fca6c2ca5c033820cea92", size = 307688, upload-time = "2025-04-15T17:37:11.481Z" }, + { url = "https://files.pythonhosted.org/packages/fc/97/e1d5dbbfa170725ef78357a9a0edc996b09ae4af170927ba8ce977e60a5f/contourpy-1.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d14f12932a8d620e307f715857107b1d1845cc44fdb5da2bc8e850f5ceba9f87", size = 347331, upload-time = "2025-04-15T17:37:18.212Z" }, + { url = "https://files.pythonhosted.org/packages/6f/66/e69e6e904f5ecf6901be3dd16e7e54d41b6ec6ae3405a535286d4418ffb4/contourpy-1.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:532fd26e715560721bb0d5fc7610fce279b3699b018600ab999d1be895b09415", size = 318963, upload-time = "2025-04-15T17:37:22.76Z" }, + { url = "https://files.pythonhosted.org/packages/a8/32/b8a1c8965e4f72482ff2d1ac2cd670ce0b542f203c8e1d34e7c3e6925da7/contourpy-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b383144cf2d2c29f01a1e8170f50dacf0eac02d64139dcd709a8ac4eb3cfe", size = 323681, upload-time = "2025-04-15T17:37:33.001Z" }, + { url = "https://files.pythonhosted.org/packages/30/c6/12a7e6811d08757c7162a541ca4c5c6a34c0f4e98ef2b338791093518e40/contourpy-1.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49f73e61f1f774650a55d221803b101d966ca0c5a2d6d5e4320ec3997489441", size = 1308674, upload-time = "2025-04-15T17:37:48.64Z" }, + { url = "https://files.pythonhosted.org/packages/2a/8a/bebe5a3f68b484d3a2b8ffaf84704b3e343ef1addea528132ef148e22b3b/contourpy-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d80b2c0300583228ac98d0a927a1ba6a2ba6b8a742463c564f1d419ee5b211e", size = 1380480, upload-time = "2025-04-15T17:38:06.7Z" }, + { url = "https://files.pythonhosted.org/packages/34/db/fcd325f19b5978fb509a7d55e06d99f5f856294c1991097534360b307cf1/contourpy-1.3.2-cp312-cp312-win32.whl", hash = "sha256:90df94c89a91b7362e1142cbee7568f86514412ab8a2c0d0fca72d7e91b62912", size = 178489, upload-time = "2025-04-15T17:38:10.338Z" }, + { url = "https://files.pythonhosted.org/packages/01/c8/fadd0b92ffa7b5eb5949bf340a63a4a496a6930a6c37a7ba0f12acb076d6/contourpy-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c942a01d9163e2e5cfb05cb66110121b8d07ad438a17f9e766317bcb62abf73", size = 223042, upload-time = "2025-04-15T17:38:14.239Z" }, + { url = "https://files.pythonhosted.org/packages/2e/61/5673f7e364b31e4e7ef6f61a4b5121c5f170f941895912f773d95270f3a2/contourpy-1.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de39db2604ae755316cb5967728f4bea92685884b1e767b7c24e983ef5f771cb", size = 271630, upload-time = "2025-04-15T17:38:19.142Z" }, + { url = "https://files.pythonhosted.org/packages/ff/66/a40badddd1223822c95798c55292844b7e871e50f6bfd9f158cb25e0bd39/contourpy-1.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3f9e896f447c5c8618f1edb2bafa9a4030f22a575ec418ad70611450720b5b08", size = 255670, upload-time = "2025-04-15T17:38:23.688Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c7/cf9fdee8200805c9bc3b148f49cb9482a4e3ea2719e772602a425c9b09f8/contourpy-1.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71e2bd4a1c4188f5c2b8d274da78faab884b59df20df63c34f74aa1813c4427c", size = 306694, upload-time = "2025-04-15T17:38:28.238Z" }, + { url = "https://files.pythonhosted.org/packages/dd/e7/ccb9bec80e1ba121efbffad7f38021021cda5be87532ec16fd96533bb2e0/contourpy-1.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de425af81b6cea33101ae95ece1f696af39446db9682a0b56daaa48cfc29f38f", size = 345986, upload-time = "2025-04-15T17:38:33.502Z" }, + { url = "https://files.pythonhosted.org/packages/dc/49/ca13bb2da90391fa4219fdb23b078d6065ada886658ac7818e5441448b78/contourpy-1.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:977e98a0e0480d3fe292246417239d2d45435904afd6d7332d8455981c408b85", size = 318060, upload-time = "2025-04-15T17:38:38.672Z" }, + { url = "https://files.pythonhosted.org/packages/c8/65/5245ce8c548a8422236c13ffcdcdada6a2a812c361e9e0c70548bb40b661/contourpy-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:434f0adf84911c924519d2b08fc10491dd282b20bdd3fa8f60fd816ea0b48841", size = 322747, upload-time = "2025-04-15T17:38:43.712Z" }, + { url = "https://files.pythonhosted.org/packages/72/30/669b8eb48e0a01c660ead3752a25b44fdb2e5ebc13a55782f639170772f9/contourpy-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c66c4906cdbc50e9cba65978823e6e00b45682eb09adbb78c9775b74eb222422", size = 1308895, upload-time = "2025-04-15T17:39:00.224Z" }, + { url = "https://files.pythonhosted.org/packages/05/5a/b569f4250decee6e8d54498be7bdf29021a4c256e77fe8138c8319ef8eb3/contourpy-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8b7fc0cd78ba2f4695fd0a6ad81a19e7e3ab825c31b577f384aa9d7817dc3bef", size = 1379098, upload-time = "2025-04-15T17:43:29.649Z" }, + { url = "https://files.pythonhosted.org/packages/19/ba/b227c3886d120e60e41b28740ac3617b2f2b971b9f601c835661194579f1/contourpy-1.3.2-cp313-cp313-win32.whl", hash = "sha256:15ce6ab60957ca74cff444fe66d9045c1fd3e92c8936894ebd1f3eef2fff075f", size = 178535, upload-time = "2025-04-15T17:44:44.532Z" }, + { url = "https://files.pythonhosted.org/packages/12/6e/2fed56cd47ca739b43e892707ae9a13790a486a3173be063681ca67d2262/contourpy-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1578f7eafce927b168752ed7e22646dad6cd9bca673c60bff55889fa236ebf9", size = 223096, upload-time = "2025-04-15T17:44:48.194Z" }, + { url = "https://files.pythonhosted.org/packages/54/4c/e76fe2a03014a7c767d79ea35c86a747e9325537a8b7627e0e5b3ba266b4/contourpy-1.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0475b1f6604896bc7c53bb070e355e9321e1bc0d381735421a2d2068ec56531f", size = 285090, upload-time = "2025-04-15T17:43:34.084Z" }, + { url = "https://files.pythonhosted.org/packages/7b/e2/5aba47debd55d668e00baf9651b721e7733975dc9fc27264a62b0dd26eb8/contourpy-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c85bb486e9be652314bb5b9e2e3b0d1b2e643d5eec4992c0fbe8ac71775da739", size = 268643, upload-time = "2025-04-15T17:43:38.626Z" }, + { url = "https://files.pythonhosted.org/packages/a1/37/cd45f1f051fe6230f751cc5cdd2728bb3a203f5619510ef11e732109593c/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:745b57db7758f3ffc05a10254edd3182a2a83402a89c00957a8e8a22f5582823", size = 310443, upload-time = "2025-04-15T17:43:44.522Z" }, + { url = "https://files.pythonhosted.org/packages/8b/a2/36ea6140c306c9ff6dd38e3bcec80b3b018474ef4d17eb68ceecd26675f4/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:970e9173dbd7eba9b4e01aab19215a48ee5dd3f43cef736eebde064a171f89a5", size = 349865, upload-time = "2025-04-15T17:43:49.545Z" }, + { url = "https://files.pythonhosted.org/packages/95/b7/2fc76bc539693180488f7b6cc518da7acbbb9e3b931fd9280504128bf956/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c4639a9c22230276b7bffb6a850dfc8258a2521305e1faefe804d006b2e532", size = 321162, upload-time = "2025-04-15T17:43:54.203Z" }, + { url = "https://files.pythonhosted.org/packages/f4/10/76d4f778458b0aa83f96e59d65ece72a060bacb20cfbee46cf6cd5ceba41/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc829960f34ba36aad4302e78eabf3ef16a3a100863f0d4eeddf30e8a485a03b", size = 327355, upload-time = "2025-04-15T17:44:01.025Z" }, + { url = "https://files.pythonhosted.org/packages/43/a3/10cf483ea683f9f8ab096c24bad3cce20e0d1dd9a4baa0e2093c1c962d9d/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d32530b534e986374fc19eaa77fcb87e8a99e5431499949b828312bdcd20ac52", size = 1307935, upload-time = "2025-04-15T17:44:17.322Z" }, + { url = "https://files.pythonhosted.org/packages/78/73/69dd9a024444489e22d86108e7b913f3528f56cfc312b5c5727a44188471/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e298e7e70cf4eb179cc1077be1c725b5fd131ebc81181bf0c03525c8abc297fd", size = 1372168, upload-time = "2025-04-15T17:44:33.43Z" }, + { url = "https://files.pythonhosted.org/packages/0f/1b/96d586ccf1b1a9d2004dd519b25fbf104a11589abfd05484ff12199cca21/contourpy-1.3.2-cp313-cp313t-win32.whl", hash = "sha256:d0e589ae0d55204991450bb5c23f571c64fe43adaa53f93fc902a84c96f52fe1", size = 189550, upload-time = "2025-04-15T17:44:37.092Z" }, + { url = "https://files.pythonhosted.org/packages/b0/e6/6000d0094e8a5e32ad62591c8609e269febb6e4db83a1c75ff8868b42731/contourpy-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:78e9253c3de756b3f6a5174d024c4835acd59eb3f8e2ca13e775dbffe1558f69", size = 238214, upload-time = "2025-04-15T17:44:40.827Z" }, + { url = "https://files.pythonhosted.org/packages/33/05/b26e3c6ecc05f349ee0013f0bb850a761016d89cec528a98193a48c34033/contourpy-1.3.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fd93cc7f3139b6dd7aab2f26a90dde0aa9fc264dbf70f6740d498a70b860b82c", size = 265681, upload-time = "2025-04-15T17:44:59.314Z" }, + { url = "https://files.pythonhosted.org/packages/2b/25/ac07d6ad12affa7d1ffed11b77417d0a6308170f44ff20fa1d5aa6333f03/contourpy-1.3.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:107ba8a6a7eec58bb475329e6d3b95deba9440667c4d62b9b6063942b61d7f16", size = 315101, upload-time = "2025-04-15T17:45:04.165Z" }, + { url = "https://files.pythonhosted.org/packages/8f/4d/5bb3192bbe9d3f27e3061a6a8e7733c9120e203cb8515767d30973f71030/contourpy-1.3.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ded1706ed0c1049224531b81128efbd5084598f18d8a2d9efae833edbd2b40ad", size = 220599, upload-time = "2025-04-15T17:45:08.456Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c0/91f1215d0d9f9f343e4773ba6c9b89e8c0cc7a64a6263f21139da639d848/contourpy-1.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5f5964cdad279256c084b69c3f412b7801e15356b16efa9d78aa974041903da0", size = 266807, upload-time = "2025-04-15T17:45:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/d4/79/6be7e90c955c0487e7712660d6cead01fa17bff98e0ea275737cc2bc8e71/contourpy-1.3.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49b65a95d642d4efa8f64ba12558fcb83407e58a2dfba9d796d77b63ccfcaff5", size = 318729, upload-time = "2025-04-15T17:45:20.166Z" }, + { url = "https://files.pythonhosted.org/packages/87/68/7f46fb537958e87427d98a4074bcde4b67a70b04900cfc5ce29bc2f556c1/contourpy-1.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8c5acb8dddb0752bf252e01a3035b21443158910ac16a3b0d20e7fed7d534ce5", size = 221791, upload-time = "2025-04-15T17:45:24.794Z" }, +] + +[[package]] +name = "contourpy" +version = "1.3.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", +] +dependencies = [ + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1", size = 288773, upload-time = "2025-07-26T12:01:02.277Z" }, + { url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381", size = 270149, upload-time = "2025-07-26T12:01:04.072Z" }, + { url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7", size = 329222, upload-time = "2025-07-26T12:01:05.688Z" }, + { url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1", size = 377234, upload-time = "2025-07-26T12:01:07.054Z" }, + { url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a", size = 380555, upload-time = "2025-07-26T12:01:08.801Z" }, + { url = "https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db", size = 355238, upload-time = "2025-07-26T12:01:10.319Z" }, + { url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620", size = 1326218, upload-time = "2025-07-26T12:01:12.659Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f", size = 1392867, upload-time = "2025-07-26T12:01:15.533Z" }, + { url = "https://files.pythonhosted.org/packages/75/3e/f2cc6cd56dc8cff46b1a56232eabc6feea52720083ea71ab15523daab796/contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff", size = 183677, upload-time = "2025-07-26T12:01:17.088Z" }, + { url = "https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42", size = 225234, upload-time = "2025-07-26T12:01:18.256Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b6/71771e02c2e004450c12b1120a5f488cad2e4d5b590b1af8bad060360fe4/contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470", size = 193123, upload-time = "2025-07-26T12:01:19.848Z" }, + { url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z" }, + { url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z" }, + { url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z" }, + { url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z" }, + { url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z" }, + { url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z" }, + { url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z" }, + { url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z" }, + { url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z" }, + { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, + { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, + { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, + { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, + { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, + { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, + { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, + { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, + { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, + { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, + { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, + { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, + { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, + { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, + { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, + { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, + { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, + { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, + { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, + { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, + { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, + { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, + { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, + { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, + { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, + { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, + { url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809, upload-time = "2025-07-26T12:02:52.74Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593, upload-time = "2025-07-26T12:02:54.037Z" }, + { url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202, upload-time = "2025-07-26T12:02:55.947Z" }, + { url = "https://files.pythonhosted.org/packages/3c/37/21972a15834d90bfbfb009b9d004779bd5a07a0ec0234e5ba8f64d5736f4/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989", size = 329207, upload-time = "2025-07-26T12:02:57.468Z" }, + { url = "https://files.pythonhosted.org/packages/0c/58/bd257695f39d05594ca4ad60df5bcb7e32247f9951fd09a9b8edb82d1daa/contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77", size = 225315, upload-time = "2025-07-26T12:02:58.801Z" }, +] + +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, +] + +[[package]] +name = "cymem" +version = "2.0.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/4a/1acd761fb6ac4c560e823ce40536a62f886f2d59b2763b5c3fc7e9d92101/cymem-2.0.11.tar.gz", hash = "sha256:efe49a349d4a518be6b6c6b255d4a80f740a341544bde1a807707c058b88d0bd", size = 10346, upload-time = "2025-01-16T21:50:41.045Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/55/f453f2b2f560e057f20eb2acdaafbf6488d72a6e8a36a4aef30f6053a51c/cymem-2.0.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1b4dd8f8c2475c7c9948eefa89c790d83134600858d8d43b90276efd8df3882e", size = 41886, upload-time = "2025-01-16T21:49:17.183Z" }, + { url = "https://files.pythonhosted.org/packages/a6/9d/03299eff35bd4fd80db33e4fd516661b82bb7b898cb677829acf22391ede/cymem-2.0.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d46ba0d2e0f749195297d16f2286b55af7d7c084db2b853fdfccece2c000c5dc", size = 41696, upload-time = "2025-01-16T21:49:18.788Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0c/90aa41f258a67ea210886c5c73f88dc9f120b7a20e6b5d92c5ce73a68276/cymem-2.0.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:739c4336b9d04ce9761851e9260ef77508d4a86ee3060e41302bfb6fa82c37de", size = 203719, upload-time = "2025-01-16T21:49:23.13Z" }, + { url = "https://files.pythonhosted.org/packages/52/d1/dc4a72aa2049c34a53a220290b1a59fadae61929dff3a6e1a830a22971fe/cymem-2.0.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a69c470c2fb118161f49761f9137384f46723c77078b659bba33858e19e46b49", size = 204763, upload-time = "2025-01-16T21:49:26.164Z" }, + { url = "https://files.pythonhosted.org/packages/69/51/86ed323585530558bcdda1324c570abe032db2c1d5afd1c5e8e3e8fde63a/cymem-2.0.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:40159f6c92627438de970fd761916e745d70dfd84a7dcc28c1627eb49cee00d8", size = 193964, upload-time = "2025-01-16T21:49:28.057Z" }, + { url = "https://files.pythonhosted.org/packages/ed/0c/aee4ad2996a4e24342228ccf44d7835c7784042f0ee0c47ad33be1443f18/cymem-2.0.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f503f98e6aa333fffbe657a6854f13a9c3de68860795ae21171284213b9c5c09", size = 195002, upload-time = "2025-01-16T21:49:31.329Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d5/eda823d639258d2ed1db83403c991a9a57d5a4ddea3bf08e59060809a9aa/cymem-2.0.11-cp310-cp310-win_amd64.whl", hash = "sha256:7f05ed5920cc92d6b958ec5da55bd820d326fe9332b90660e6fa67e3b476ceb1", size = 39079, upload-time = "2025-01-16T21:49:33.777Z" }, + { url = "https://files.pythonhosted.org/packages/03/e3/d98e3976f4ffa99cddebc1ce379d4d62e3eb1da22285267f902c99cc3395/cymem-2.0.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3ee54039aad3ef65de82d66c40516bf54586287b46d32c91ea0530c34e8a2745", size = 42005, upload-time = "2025-01-16T21:49:34.977Z" }, + { url = "https://files.pythonhosted.org/packages/41/b4/7546faf2ab63e59befc95972316d62276cec153f7d4d60e7b0d5e08f0602/cymem-2.0.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c05ef75b5db217be820604e43a47ccbbafea98ab6659d07cea92fa3c864ea58", size = 41747, upload-time = "2025-01-16T21:49:36.108Z" }, + { url = "https://files.pythonhosted.org/packages/7d/4e/042f372e5b3eb7f5f3dd7677161771d301de2b6fa3f7c74e1cebcd502552/cymem-2.0.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8d5381e5793ce531bac0dbc00829c8381f18605bb67e4b61d34f8850463da40", size = 217647, upload-time = "2025-01-16T21:49:37.433Z" }, + { url = "https://files.pythonhosted.org/packages/48/cb/2207679e4b92701f78cf141e1ab4f81f55247dbe154eb426b842a0a993de/cymem-2.0.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2b9d3f42d7249ac81802135cad51d707def058001a32f73fc7fbf3de7045ac7", size = 218857, upload-time = "2025-01-16T21:49:40.09Z" }, + { url = "https://files.pythonhosted.org/packages/31/7a/76ae3b7a39ab2531029d281e43fcfcaad728c2341b150a81a3a1f5587cf3/cymem-2.0.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:39b78f2195d20b75c2d465732f6b8e8721c5d4eb012777c2cb89bdb45a043185", size = 206148, upload-time = "2025-01-16T21:49:41.383Z" }, + { url = "https://files.pythonhosted.org/packages/25/f9/d0fc0191ac79f15638ddb59237aa76f234691374d7d7950e10f384bd8a25/cymem-2.0.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2203bd6525a80d8fd0c94654a263af21c0387ae1d5062cceaebb652bf9bad7bc", size = 207112, upload-time = "2025-01-16T21:49:43.986Z" }, + { url = "https://files.pythonhosted.org/packages/56/c8/75f75889401b20f4c3a7c5965dda09df42913e904ddc2ffe7ef3bdf25061/cymem-2.0.11-cp311-cp311-win_amd64.whl", hash = "sha256:aa54af7314de400634448da1f935b61323da80a49484074688d344fb2036681b", size = 39360, upload-time = "2025-01-16T21:49:45.479Z" }, + { url = "https://files.pythonhosted.org/packages/71/67/0d74f7e9d79f934368a78fb1d1466b94bebdbff14f8ae94dd3e4ea8738bb/cymem-2.0.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a0fbe19ce653cd688842d81e5819dc63f911a26e192ef30b0b89f0ab2b192ff2", size = 42621, upload-time = "2025-01-16T21:49:46.585Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d6/f7a19c63b48efc3f00a3ee8d69070ac90202e1e378f6cf81b8671f0cf762/cymem-2.0.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de72101dc0e6326f6a2f73e05a438d1f3c6110d41044236d0fbe62925091267d", size = 42249, upload-time = "2025-01-16T21:49:48.973Z" }, + { url = "https://files.pythonhosted.org/packages/d7/60/cdc434239813eef547fb99b6d0bafe31178501702df9b77c4108c9a216f6/cymem-2.0.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee4395917f6588b8ac1699499128842768b391fe8896e8626950b4da5f9a406", size = 224758, upload-time = "2025-01-16T21:49:51.382Z" }, + { url = "https://files.pythonhosted.org/packages/1d/68/8fa6efae17cd3b2ba9a2f83b824867c5b65b06f7aec3f8a0d0cabdeffb9b/cymem-2.0.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02f2b17d760dc3fe5812737b1ce4f684641cdd751d67761d333a3b5ea97b83", size = 227995, upload-time = "2025-01-16T21:49:54.538Z" }, + { url = "https://files.pythonhosted.org/packages/e4/f3/ceda70bf6447880140602285b7c6fa171cb7c78b623d35345cc32505cd06/cymem-2.0.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:04ee6b4041ddec24512d6e969ed6445e57917f01e73b9dabbe17b7e6b27fef05", size = 215325, upload-time = "2025-01-16T21:49:57.229Z" }, + { url = "https://files.pythonhosted.org/packages/d3/47/6915eaa521e1ce7a0ba480eecb6870cb4f681bcd64ced88c2f0ed7a744b4/cymem-2.0.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e1048dae7e627ee25f22c87bb670b13e06bc0aecc114b89b959a798d487d1bf4", size = 216447, upload-time = "2025-01-16T21:50:00.432Z" }, + { url = "https://files.pythonhosted.org/packages/7b/be/8e02bdd31e557f642741a06c8e886782ef78f0b00daffd681922dc9bbc88/cymem-2.0.11-cp312-cp312-win_amd64.whl", hash = "sha256:0c269c7a867d74adeb9db65fa1d226342aacf44d64b7931282f0b0eb22eb6275", size = 39283, upload-time = "2025-01-16T21:50:03.384Z" }, + { url = "https://files.pythonhosted.org/packages/bd/90/b064e2677e27a35cf3605146abc3285d4f599cc1b6c18fc445ae876dd1e3/cymem-2.0.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4a311c82f743275c84f708df89ac5bf60ddefe4713d532000c887931e22941f", size = 42389, upload-time = "2025-01-16T21:50:05.925Z" }, + { url = "https://files.pythonhosted.org/packages/fd/60/7aa0561a6c1f0d42643b02c4fdeb2a16181b0ff4e85d73d2d80c6689e92a/cymem-2.0.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:02ed92bead896cca36abad00502b14fa651bdf5d8319461126a2d5ac8c9674c5", size = 41948, upload-time = "2025-01-16T21:50:08.375Z" }, + { url = "https://files.pythonhosted.org/packages/5f/4e/88a29cc5575374982e527b4ebcab3781bdc826ce693c6418a0f836544246/cymem-2.0.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44ddd3588379f8f376116384af99e3fb5f90091d90f520c341942618bf22f05e", size = 219382, upload-time = "2025-01-16T21:50:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/9b/3a/8f96e167e93b7f7ec105ed7b25c77bbf215d15bcbf4a24082cdc12234cd6/cymem-2.0.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87ec985623624bbd298762d8163fc194a096cb13282731a017e09ff8a60bb8b1", size = 222974, upload-time = "2025-01-16T21:50:17.969Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fc/ce016bb0c66a4776345fac7508fddec3b739b9dd4363094ac89cce048832/cymem-2.0.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3385a47285435848e0ed66cfd29b35f3ed8703218e2b17bd7a0c053822f26bf", size = 213426, upload-time = "2025-01-16T21:50:19.349Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c8/accf7cc768f751447a5050b14a195af46798bc22767ac25f49b02861b1eb/cymem-2.0.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5461e65340d6572eb64deadce79242a446a1d39cb7bf70fe7b7e007eb0d799b0", size = 219195, upload-time = "2025-01-16T21:50:21.407Z" }, + { url = "https://files.pythonhosted.org/packages/74/65/c162fbac63e867a055240b6600b92ef96c0eb7a1895312ac53c4be93d056/cymem-2.0.11-cp313-cp313-win_amd64.whl", hash = "sha256:25da111adf425c29af0cfd9fecfec1c71c8d82e2244a85166830a0817a66ada7", size = 39090, upload-time = "2025-01-16T21:50:24.239Z" }, +] + +[[package]] +name = "datasets" +version = "4.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dill" }, + { name = "filelock" }, + { name = "fsspec", extra = ["http"] }, + { name = "httpx" }, + { name = "huggingface-hub" }, + { name = "multiprocess" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging" }, + { name = "pandas" }, + { name = "pyarrow" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "tqdm" }, + { name = "xxhash" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2a/47/325206ac160f7699ed9f1798afa8f8f8d5189b03bf3815654859ac1d5cba/datasets-4.3.0.tar.gz", hash = "sha256:bc9118ed9afd92346c5be7ed3aaa00177eb907c25467f9d072a0d22777efbd2b", size = 582801, upload-time = "2025-10-23T16:31:51.547Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/51/409a8184ed35453d9cbb3d6b20d524b1115c2c2d117b85d5e9b06cd70b45/datasets-4.3.0-py3-none-any.whl", hash = "sha256:0ea157e72138b3ca6c7d2415f19a164ecf7d4c4fa72da2a570da286882e96903", size = 506846, upload-time = "2025-10-23T16:31:49.965Z" }, +] + +[[package]] +name = "dill" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976, upload-time = "2025-04-16T00:41:48.867Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668, upload-time = "2025-04-16T00:41:47.671Z" }, +] + +[[package]] +name = "evaluate" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "datasets" }, + { name = "dill" }, + { name = "fsspec", extra = ["http"] }, + { name = "huggingface-hub" }, + { name = "multiprocess" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging" }, + { name = "pandas" }, + { name = "requests" }, + { name = "tqdm" }, + { name = "xxhash" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/d0/0c17a8e6e8dc7245f22dea860557c32bae50fc4d287ae030cb0e8ab8720f/evaluate-0.4.6.tar.gz", hash = "sha256:e07036ca12b3c24331f83ab787f21cc2dbf3631813a1631e63e40897c69a3f21", size = 65716, upload-time = "2025-09-18T13:06:30.581Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3e/af/3e990d8d4002bbc9342adb4facd59506e653da93b2417de0fa6027cb86b1/evaluate-0.4.6-py3-none-any.whl", hash = "sha256:bca85bc294f338377b7ac2f861e21c308b11b2a285f510d7d5394d5df437db29", size = 84069, upload-time = "2025-09-18T13:06:29.265Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + +[[package]] +name = "filelock" +version = "3.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/46/0028a82567109b5ef6e4d2a1f04a583fb513e6cf9527fcdd09afd817deeb/filelock-3.20.0.tar.gz", hash = "sha256:711e943b4ec6be42e1d4e6690b48dc175c822967466bb31c0c293f34334c13f4", size = 18922, upload-time = "2025-10-08T18:03:50.056Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/91/7216b27286936c16f5b4d0c530087e4a54eead683e6b0b73dd0c64844af6/filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2", size = 16054, upload-time = "2025-10-08T18:03:48.35Z" }, +] + +[[package]] +name = "flashtrace" +version = "0.1.1" +source = { editable = "." } +dependencies = [ + { name = "accelerate" }, + { name = "matplotlib" }, + { name = "networkx" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "seaborn" }, + { name = "spacy" }, + { name = "torch" }, + { name = "tqdm" }, + { name = "transformers" }, + { name = "wordfreq" }, +] + +[package.optional-dependencies] +baselines = [ + { name = "bert-score" }, + { name = "evaluate" }, + { name = "sentence-transformers" }, +] +dev = [ + { name = "pytest" }, +] +eval = [ + { name = "datasets" }, + { name = "evaluate" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, +] + +[package.metadata] +requires-dist = [ + { name = "accelerate", specifier = ">=1.11.0" }, + { name = "bert-score", marker = "extra == 'baselines'", specifier = ">=0.3.13" }, + { name = "datasets", marker = "extra == 'eval'", specifier = ">=2.21" }, + { name = "evaluate", marker = "extra == 'baselines'", specifier = ">=0.4.6" }, + { name = "evaluate", marker = "extra == 'eval'", specifier = ">=0.4.6" }, + { name = "matplotlib", specifier = ">=3.6" }, + { name = "networkx", specifier = ">=3.3" }, + { name = "numpy", specifier = ">=2.0" }, + { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" }, + { name = "seaborn", specifier = ">=0.13.2" }, + { name = "sentence-transformers", marker = "extra == 'baselines'", specifier = ">=4.1.0" }, + { name = "spacy", specifier = ">=3.8" }, + { name = "torch", specifier = ">=2.5" }, + { name = "tqdm", specifier = ">=4.67" }, + { name = "transformers", specifier = ">=4.53" }, + { name = "wordfreq", specifier = ">=3.1.1" }, +] +provides-extras = ["baselines", "eval", "dev"] + +[package.metadata.requires-dev] +dev = [{ name = "pytest", specifier = ">=8.0" }] + +[[package]] +name = "fonttools" +version = "4.60.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/42/97a13e47a1e51a5a7142475bbcf5107fe3a68fc34aef331c897d5fb98ad0/fonttools-4.60.1.tar.gz", hash = "sha256:ef00af0439ebfee806b25f24c8f92109157ff3fac5731dc7867957812e87b8d9", size = 3559823, upload-time = "2025-09-29T21:13:27.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/70/03e9d89a053caff6ae46053890eba8e4a5665a7c5638279ed4492e6d4b8b/fonttools-4.60.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9a52f254ce051e196b8fe2af4634c2d2f02c981756c6464dc192f1b6050b4e28", size = 2810747, upload-time = "2025-09-29T21:10:59.653Z" }, + { url = "https://files.pythonhosted.org/packages/6f/41/449ad5aff9670ab0df0f61ee593906b67a36d7e0b4d0cd7fa41ac0325bf5/fonttools-4.60.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7420a2696a44650120cdd269a5d2e56a477e2bfa9d95e86229059beb1c19e15", size = 2346909, upload-time = "2025-09-29T21:11:02.882Z" }, + { url = "https://files.pythonhosted.org/packages/9a/18/e5970aa96c8fad1cb19a9479cc3b7602c0c98d250fcdc06a5da994309c50/fonttools-4.60.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee0c0b3b35b34f782afc673d503167157094a16f442ace7c6c5e0ca80b08f50c", size = 4864572, upload-time = "2025-09-29T21:11:05.096Z" }, + { url = "https://files.pythonhosted.org/packages/ce/20/9b2b4051b6ec6689480787d506b5003f72648f50972a92d04527a456192c/fonttools-4.60.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:282dafa55f9659e8999110bd8ed422ebe1c8aecd0dc396550b038e6c9a08b8ea", size = 4794635, upload-time = "2025-09-29T21:11:08.651Z" }, + { url = "https://files.pythonhosted.org/packages/10/52/c791f57347c1be98f8345e3dca4ac483eb97666dd7c47f3059aeffab8b59/fonttools-4.60.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4ba4bd646e86de16160f0fb72e31c3b9b7d0721c3e5b26b9fa2fc931dfdb2652", size = 4843878, upload-time = "2025-09-29T21:11:10.893Z" }, + { url = "https://files.pythonhosted.org/packages/69/e9/35c24a8d01644cee8c090a22fad34d5b61d1e0a8ecbc9945ad785ebf2e9e/fonttools-4.60.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0b0835ed15dd5b40d726bb61c846a688f5b4ce2208ec68779bc81860adb5851a", size = 4954555, upload-time = "2025-09-29T21:11:13.24Z" }, + { url = "https://files.pythonhosted.org/packages/f7/86/fb1e994971be4bdfe3a307de6373ef69a9df83fb66e3faa9c8114893d4cc/fonttools-4.60.1-cp310-cp310-win32.whl", hash = "sha256:1525796c3ffe27bb6268ed2a1bb0dcf214d561dfaf04728abf01489eb5339dce", size = 2232019, upload-time = "2025-09-29T21:11:15.73Z" }, + { url = "https://files.pythonhosted.org/packages/40/84/62a19e2bd56f0e9fb347486a5b26376bade4bf6bbba64dda2c103bd08c94/fonttools-4.60.1-cp310-cp310-win_amd64.whl", hash = "sha256:268ecda8ca6cb5c4f044b1fb9b3b376e8cd1b361cef275082429dc4174907038", size = 2276803, upload-time = "2025-09-29T21:11:18.152Z" }, + { url = "https://files.pythonhosted.org/packages/ea/85/639aa9bface1537e0fb0f643690672dde0695a5bbbc90736bc571b0b1941/fonttools-4.60.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7b4c32e232a71f63a5d00259ca3d88345ce2a43295bb049d21061f338124246f", size = 2831872, upload-time = "2025-09-29T21:11:20.329Z" }, + { url = "https://files.pythonhosted.org/packages/6b/47/3c63158459c95093be9618794acb1067b3f4d30dcc5c3e8114b70e67a092/fonttools-4.60.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3630e86c484263eaac71d117085d509cbcf7b18f677906824e4bace598fb70d2", size = 2356990, upload-time = "2025-09-29T21:11:22.754Z" }, + { url = "https://files.pythonhosted.org/packages/94/dd/1934b537c86fcf99f9761823f1fc37a98fbd54568e8e613f29a90fed95a9/fonttools-4.60.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5c1015318e4fec75dd4943ad5f6a206d9727adf97410d58b7e32ab644a807914", size = 5042189, upload-time = "2025-09-29T21:11:25.061Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d2/9f4e4c4374dd1daa8367784e1bd910f18ba886db1d6b825b12edf6db3edc/fonttools-4.60.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e6c58beb17380f7c2ea181ea11e7db8c0ceb474c9dd45f48e71e2cb577d146a1", size = 4978683, upload-time = "2025-09-29T21:11:27.693Z" }, + { url = "https://files.pythonhosted.org/packages/cc/c4/0fb2dfd1ecbe9a07954cc13414713ed1eab17b1c0214ef07fc93df234a47/fonttools-4.60.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec3681a0cb34c255d76dd9d865a55f260164adb9fa02628415cdc2d43ee2c05d", size = 5021372, upload-time = "2025-09-29T21:11:30.257Z" }, + { url = "https://files.pythonhosted.org/packages/0c/d5/495fc7ae2fab20223cc87179a8f50f40f9a6f821f271ba8301ae12bb580f/fonttools-4.60.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f4b5c37a5f40e4d733d3bbaaef082149bee5a5ea3156a785ff64d949bd1353fa", size = 5132562, upload-time = "2025-09-29T21:11:32.737Z" }, + { url = "https://files.pythonhosted.org/packages/bc/fa/021dab618526323c744e0206b3f5c8596a2e7ae9aa38db5948a131123e83/fonttools-4.60.1-cp311-cp311-win32.whl", hash = "sha256:398447f3d8c0c786cbf1209711e79080a40761eb44b27cdafffb48f52bcec258", size = 2230288, upload-time = "2025-09-29T21:11:35.015Z" }, + { url = "https://files.pythonhosted.org/packages/bb/78/0e1a6d22b427579ea5c8273e1c07def2f325b977faaf60bb7ddc01456cb1/fonttools-4.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:d066ea419f719ed87bc2c99a4a4bfd77c2e5949cb724588b9dd58f3fd90b92bf", size = 2278184, upload-time = "2025-09-29T21:11:37.434Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f7/a10b101b7a6f8836a5adb47f2791f2075d044a6ca123f35985c42edc82d8/fonttools-4.60.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7b0c6d57ab00dae9529f3faf187f2254ea0aa1e04215cf2f1a8ec277c96661bc", size = 2832953, upload-time = "2025-09-29T21:11:39.616Z" }, + { url = "https://files.pythonhosted.org/packages/ed/fe/7bd094b59c926acf2304d2151354ddbeb74b94812f3dc943c231db09cb41/fonttools-4.60.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:839565cbf14645952d933853e8ade66a463684ed6ed6c9345d0faf1f0e868877", size = 2352706, upload-time = "2025-09-29T21:11:41.826Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ca/4bb48a26ed95a1e7eba175535fe5805887682140ee0a0d10a88e1de84208/fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8177ec9676ea6e1793c8a084a90b65a9f778771998eb919d05db6d4b1c0b114c", size = 4923716, upload-time = "2025-09-29T21:11:43.893Z" }, + { url = "https://files.pythonhosted.org/packages/b8/9f/2cb82999f686c1d1ddf06f6ae1a9117a880adbec113611cc9d22b2fdd465/fonttools-4.60.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:996a4d1834524adbb423385d5a629b868ef9d774670856c63c9a0408a3063401", size = 4968175, upload-time = "2025-09-29T21:11:46.439Z" }, + { url = "https://files.pythonhosted.org/packages/18/79/be569699e37d166b78e6218f2cde8c550204f2505038cdd83b42edc469b9/fonttools-4.60.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a46b2f450bc79e06ef3b6394f0c68660529ed51692606ad7f953fc2e448bc903", size = 4911031, upload-time = "2025-09-29T21:11:48.977Z" }, + { url = "https://files.pythonhosted.org/packages/cc/9f/89411cc116effaec5260ad519162f64f9c150e5522a27cbb05eb62d0c05b/fonttools-4.60.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ec722ee589e89a89f5b7574f5c45604030aa6ae24cb2c751e2707193b466fed", size = 5062966, upload-time = "2025-09-29T21:11:54.344Z" }, + { url = "https://files.pythonhosted.org/packages/62/a1/f888221934b5731d46cb9991c7a71f30cb1f97c0ef5fcf37f8da8fce6c8e/fonttools-4.60.1-cp312-cp312-win32.whl", hash = "sha256:b2cf105cee600d2de04ca3cfa1f74f1127f8455b71dbad02b9da6ec266e116d6", size = 2218750, upload-time = "2025-09-29T21:11:56.601Z" }, + { url = "https://files.pythonhosted.org/packages/88/8f/a55b5550cd33cd1028601df41acd057d4be20efa5c958f417b0c0613924d/fonttools-4.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:992775c9fbe2cf794786fa0ffca7f09f564ba3499b8fe9f2f80bd7197db60383", size = 2267026, upload-time = "2025-09-29T21:11:58.852Z" }, + { url = "https://files.pythonhosted.org/packages/7c/5b/cdd2c612277b7ac7ec8c0c9bc41812c43dc7b2d5f2b0897e15fdf5a1f915/fonttools-4.60.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6f68576bb4bbf6060c7ab047b1574a1ebe5c50a17de62830079967b211059ebb", size = 2825777, upload-time = "2025-09-29T21:12:01.22Z" }, + { url = "https://files.pythonhosted.org/packages/d6/8a/de9cc0540f542963ba5e8f3a1f6ad48fa211badc3177783b9d5cadf79b5d/fonttools-4.60.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:eedacb5c5d22b7097482fa834bda0dafa3d914a4e829ec83cdea2a01f8c813c4", size = 2348080, upload-time = "2025-09-29T21:12:03.785Z" }, + { url = "https://files.pythonhosted.org/packages/2d/8b/371ab3cec97ee3fe1126b3406b7abd60c8fec8975fd79a3c75cdea0c3d83/fonttools-4.60.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b33a7884fabd72bdf5f910d0cf46be50dce86a0362a65cfc746a4168c67eb96c", size = 4903082, upload-time = "2025-09-29T21:12:06.382Z" }, + { url = "https://files.pythonhosted.org/packages/04/05/06b1455e4bc653fcb2117ac3ef5fa3a8a14919b93c60742d04440605d058/fonttools-4.60.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2409d5fb7b55fd70f715e6d34e7a6e4f7511b8ad29a49d6df225ee76da76dd77", size = 4960125, upload-time = "2025-09-29T21:12:09.314Z" }, + { url = "https://files.pythonhosted.org/packages/8e/37/f3b840fcb2666f6cb97038793606bdd83488dca2d0b0fc542ccc20afa668/fonttools-4.60.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c8651e0d4b3bdeda6602b85fdc2abbefc1b41e573ecb37b6779c4ca50753a199", size = 4901454, upload-time = "2025-09-29T21:12:11.931Z" }, + { url = "https://files.pythonhosted.org/packages/fd/9e/eb76f77e82f8d4a46420aadff12cec6237751b0fb9ef1de373186dcffb5f/fonttools-4.60.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:145daa14bf24824b677b9357c5e44fd8895c2a8f53596e1b9ea3496081dc692c", size = 5044495, upload-time = "2025-09-29T21:12:15.241Z" }, + { url = "https://files.pythonhosted.org/packages/f8/b3/cede8f8235d42ff7ae891bae8d619d02c8ac9fd0cfc450c5927a6200c70d/fonttools-4.60.1-cp313-cp313-win32.whl", hash = "sha256:2299df884c11162617a66b7c316957d74a18e3758c0274762d2cc87df7bc0272", size = 2217028, upload-time = "2025-09-29T21:12:17.96Z" }, + { url = "https://files.pythonhosted.org/packages/75/4d/b022c1577807ce8b31ffe055306ec13a866f2337ecee96e75b24b9b753ea/fonttools-4.60.1-cp313-cp313-win_amd64.whl", hash = "sha256:a3db56f153bd4c5c2b619ab02c5db5192e222150ce5a1bc10f16164714bc39ac", size = 2266200, upload-time = "2025-09-29T21:12:20.14Z" }, + { url = "https://files.pythonhosted.org/packages/9a/83/752ca11c1aa9a899b793a130f2e466b79ea0cf7279c8d79c178fc954a07b/fonttools-4.60.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:a884aef09d45ba1206712c7dbda5829562d3fea7726935d3289d343232ecb0d3", size = 2822830, upload-time = "2025-09-29T21:12:24.406Z" }, + { url = "https://files.pythonhosted.org/packages/57/17/bbeab391100331950a96ce55cfbbff27d781c1b85ebafb4167eae50d9fe3/fonttools-4.60.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8a44788d9d91df72d1a5eac49b31aeb887a5f4aab761b4cffc4196c74907ea85", size = 2345524, upload-time = "2025-09-29T21:12:26.819Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2e/d4831caa96d85a84dd0da1d9f90d81cec081f551e0ea216df684092c6c97/fonttools-4.60.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e852d9dda9f93ad3651ae1e3bb770eac544ec93c3807888798eccddf84596537", size = 4843490, upload-time = "2025-09-29T21:12:29.123Z" }, + { url = "https://files.pythonhosted.org/packages/49/13/5e2ea7c7a101b6fc3941be65307ef8df92cbbfa6ec4804032baf1893b434/fonttools-4.60.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:154cb6ee417e417bf5f7c42fe25858c9140c26f647c7347c06f0cc2d47eff003", size = 4944184, upload-time = "2025-09-29T21:12:31.414Z" }, + { url = "https://files.pythonhosted.org/packages/0c/2b/cf9603551c525b73fc47c52ee0b82a891579a93d9651ed694e4e2cd08bb8/fonttools-4.60.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5664fd1a9ea7f244487ac8f10340c4e37664675e8667d6fee420766e0fb3cf08", size = 4890218, upload-time = "2025-09-29T21:12:33.936Z" }, + { url = "https://files.pythonhosted.org/packages/fd/2f/933d2352422e25f2376aae74f79eaa882a50fb3bfef3c0d4f50501267101/fonttools-4.60.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:583b7f8e3c49486e4d489ad1deacfb8d5be54a8ef34d6df824f6a171f8511d99", size = 4999324, upload-time = "2025-09-29T21:12:36.637Z" }, + { url = "https://files.pythonhosted.org/packages/38/99/234594c0391221f66216bc2c886923513b3399a148defaccf81dc3be6560/fonttools-4.60.1-cp314-cp314-win32.whl", hash = "sha256:66929e2ea2810c6533a5184f938502cfdaea4bc3efb7130d8cc02e1c1b4108d6", size = 2220861, upload-time = "2025-09-29T21:12:39.108Z" }, + { url = "https://files.pythonhosted.org/packages/3e/1d/edb5b23726dde50fc4068e1493e4fc7658eeefcaf75d4c5ffce067d07ae5/fonttools-4.60.1-cp314-cp314-win_amd64.whl", hash = "sha256:f3d5be054c461d6a2268831f04091dc82753176f6ea06dc6047a5e168265a987", size = 2270934, upload-time = "2025-09-29T21:12:41.339Z" }, + { url = "https://files.pythonhosted.org/packages/fb/da/1392aaa2170adc7071fe7f9cfd181a5684a7afcde605aebddf1fb4d76df5/fonttools-4.60.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b6379e7546ba4ae4b18f8ae2b9bc5960936007a1c0e30b342f662577e8bc3299", size = 2894340, upload-time = "2025-09-29T21:12:43.774Z" }, + { url = "https://files.pythonhosted.org/packages/bf/a7/3b9f16e010d536ce567058b931a20b590d8f3177b2eda09edd92e392375d/fonttools-4.60.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9d0ced62b59e0430b3690dbc5373df1c2aa7585e9a8ce38eff87f0fd993c5b01", size = 2375073, upload-time = "2025-09-29T21:12:46.437Z" }, + { url = "https://files.pythonhosted.org/packages/9b/b5/e9bcf51980f98e59bb5bb7c382a63c6f6cac0eec5f67de6d8f2322382065/fonttools-4.60.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:875cb7764708b3132637f6c5fb385b16eeba0f7ac9fa45a69d35e09b47045801", size = 4849758, upload-time = "2025-09-29T21:12:48.694Z" }, + { url = "https://files.pythonhosted.org/packages/e3/dc/1d2cf7d1cba82264b2f8385db3f5960e3d8ce756b4dc65b700d2c496f7e9/fonttools-4.60.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a184b2ea57b13680ab6d5fbde99ccef152c95c06746cb7718c583abd8f945ccc", size = 5085598, upload-time = "2025-09-29T21:12:51.081Z" }, + { url = "https://files.pythonhosted.org/packages/5d/4d/279e28ba87fb20e0c69baf72b60bbf1c4d873af1476806a7b5f2b7fac1ff/fonttools-4.60.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:026290e4ec76583881763fac284aca67365e0be9f13a7fb137257096114cb3bc", size = 4957603, upload-time = "2025-09-29T21:12:53.423Z" }, + { url = "https://files.pythonhosted.org/packages/78/d4/ff19976305e0c05aa3340c805475abb00224c954d3c65e82c0a69633d55d/fonttools-4.60.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f0e8817c7d1a0c2eedebf57ef9a9896f3ea23324769a9a2061a80fe8852705ed", size = 4974184, upload-time = "2025-09-29T21:12:55.962Z" }, + { url = "https://files.pythonhosted.org/packages/63/22/8553ff6166f5cd21cfaa115aaacaa0dc73b91c079a8cfd54a482cbc0f4f5/fonttools-4.60.1-cp314-cp314t-win32.whl", hash = "sha256:1410155d0e764a4615774e5c2c6fc516259fe3eca5882f034eb9bfdbee056259", size = 2282241, upload-time = "2025-09-29T21:12:58.179Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cb/fa7b4d148e11d5a72761a22e595344133e83a9507a4c231df972e657579b/fonttools-4.60.1-cp314-cp314t-win_amd64.whl", hash = "sha256:022beaea4b73a70295b688f817ddc24ed3e3418b5036ffcd5658141184ef0d0c", size = 2345760, upload-time = "2025-09-29T21:13:00.375Z" }, + { url = "https://files.pythonhosted.org/packages/c7/93/0dd45cd283c32dea1545151d8c3637b4b8c53cdb3a625aeb2885b184d74d/fonttools-4.60.1-py3-none-any.whl", hash = "sha256:906306ac7afe2156fcf0042173d6ebbb05416af70f6b370967b47f8f00103bbb", size = 1143175, upload-time = "2025-09-29T21:13:24.134Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/4a/557715d5047da48d54e659203b9335be7bfaafda2c3f627b7c47e0b3aaf3/frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011", size = 86230, upload-time = "2025-10-06T05:35:23.699Z" }, + { url = "https://files.pythonhosted.org/packages/a2/fb/c85f9fed3ea8fe8740e5b46a59cc141c23b842eca617da8876cfce5f760e/frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565", size = 49621, upload-time = "2025-10-06T05:35:25.341Z" }, + { url = "https://files.pythonhosted.org/packages/63/70/26ca3f06aace16f2352796b08704338d74b6d1a24ca38f2771afbb7ed915/frozenlist-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a88f062f072d1589b7b46e951698950e7da00442fc1cacbe17e19e025dc327ad", size = 49889, upload-time = "2025-10-06T05:35:26.797Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ed/c7895fd2fde7f3ee70d248175f9b6cdf792fb741ab92dc59cd9ef3bd241b/frozenlist-1.8.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f57fb59d9f385710aa7060e89410aeb5058b99e62f4d16b08b91986b9a2140c2", size = 219464, upload-time = "2025-10-06T05:35:28.254Z" }, + { url = "https://files.pythonhosted.org/packages/6b/83/4d587dccbfca74cb8b810472392ad62bfa100bf8108c7223eb4c4fa2f7b3/frozenlist-1.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799345ab092bee59f01a915620b5d014698547afd011e691a208637312db9186", size = 221649, upload-time = "2025-10-06T05:35:29.454Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c6/fd3b9cd046ec5fff9dab66831083bc2077006a874a2d3d9247dea93ddf7e/frozenlist-1.8.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c23c3ff005322a6e16f71bf8692fcf4d5a304aaafe1e262c98c6d4adc7be863e", size = 219188, upload-time = "2025-10-06T05:35:30.951Z" }, + { url = "https://files.pythonhosted.org/packages/ce/80/6693f55eb2e085fc8afb28cf611448fb5b90e98e068fa1d1b8d8e66e5c7d/frozenlist-1.8.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a76ea0f0b9dfa06f254ee06053d93a600865b3274358ca48a352ce4f0798450", size = 231748, upload-time = "2025-10-06T05:35:32.101Z" }, + { url = "https://files.pythonhosted.org/packages/97/d6/e9459f7c5183854abd989ba384fe0cc1a0fb795a83c033f0571ec5933ca4/frozenlist-1.8.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c7366fe1418a6133d5aa824ee53d406550110984de7637d65a178010f759c6ef", size = 236351, upload-time = "2025-10-06T05:35:33.834Z" }, + { url = "https://files.pythonhosted.org/packages/97/92/24e97474b65c0262e9ecd076e826bfd1d3074adcc165a256e42e7b8a7249/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13d23a45c4cebade99340c4165bd90eeb4a56c6d8a9d8aa49568cac19a6d0dc4", size = 218767, upload-time = "2025-10-06T05:35:35.205Z" }, + { url = "https://files.pythonhosted.org/packages/ee/bf/dc394a097508f15abff383c5108cb8ad880d1f64a725ed3b90d5c2fbf0bb/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:e4a3408834f65da56c83528fb52ce7911484f0d1eaf7b761fc66001db1646eff", size = 235887, upload-time = "2025-10-06T05:35:36.354Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/25b201b9c015dbc999a5baf475a257010471a1fa8c200c843fd4abbee725/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:42145cd2748ca39f32801dad54aeea10039da6f86e303659db90db1c4b614c8c", size = 228785, upload-time = "2025-10-06T05:35:37.949Z" }, + { url = "https://files.pythonhosted.org/packages/84/f4/b5bc148df03082f05d2dd30c089e269acdbe251ac9a9cf4e727b2dbb8a3d/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e2de870d16a7a53901e41b64ffdf26f2fbb8917b3e6ebf398098d72c5b20bd7f", size = 230312, upload-time = "2025-10-06T05:35:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/db/4b/87e95b5d15097c302430e647136b7d7ab2398a702390cf4c8601975709e7/frozenlist-1.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:20e63c9493d33ee48536600d1a5c95eefc870cd71e7ab037763d1fbb89cc51e7", size = 217650, upload-time = "2025-10-06T05:35:40.377Z" }, + { url = "https://files.pythonhosted.org/packages/e5/70/78a0315d1fea97120591a83e0acd644da638c872f142fd72a6cebee825f3/frozenlist-1.8.0-cp310-cp310-win32.whl", hash = "sha256:adbeebaebae3526afc3c96fad434367cafbfd1b25d72369a9e5858453b1bb71a", size = 39659, upload-time = "2025-10-06T05:35:41.863Z" }, + { url = "https://files.pythonhosted.org/packages/66/aa/3f04523fb189a00e147e60c5b2205126118f216b0aa908035c45336e27e4/frozenlist-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:667c3777ca571e5dbeb76f331562ff98b957431df140b54c85fd4d52eea8d8f6", size = 43837, upload-time = "2025-10-06T05:35:43.205Z" }, + { url = "https://files.pythonhosted.org/packages/39/75/1135feecdd7c336938bd55b4dc3b0dfc46d85b9be12ef2628574b28de776/frozenlist-1.8.0-cp310-cp310-win_arm64.whl", hash = "sha256:80f85f0a7cc86e7a54c46d99c9e1318ff01f4687c172ede30fd52d19d1da1c8e", size = 39989, upload-time = "2025-10-06T05:35:44.596Z" }, + { url = "https://files.pythonhosted.org/packages/bc/03/077f869d540370db12165c0aa51640a873fb661d8b315d1d4d67b284d7ac/frozenlist-1.8.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:09474e9831bc2b2199fad6da3c14c7b0fbdd377cce9d3d77131be28906cb7d84", size = 86912, upload-time = "2025-10-06T05:35:45.98Z" }, + { url = "https://files.pythonhosted.org/packages/df/b5/7610b6bd13e4ae77b96ba85abea1c8cb249683217ef09ac9e0ae93f25a91/frozenlist-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:17c883ab0ab67200b5f964d2b9ed6b00971917d5d8a92df149dc2c9779208ee9", size = 50046, upload-time = "2025-10-06T05:35:47.009Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ef/0e8f1fe32f8a53dd26bdd1f9347efe0778b0fddf62789ea683f4cc7d787d/frozenlist-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa47e444b8ba08fffd1c18e8cdb9a75db1b6a27f17507522834ad13ed5922b93", size = 50119, upload-time = "2025-10-06T05:35:48.38Z" }, + { url = "https://files.pythonhosted.org/packages/11/b1/71a477adc7c36e5fb628245dfbdea2166feae310757dea848d02bd0689fd/frozenlist-1.8.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2552f44204b744fba866e573be4c1f9048d6a324dfe14475103fd51613eb1d1f", size = 231067, upload-time = "2025-10-06T05:35:49.97Z" }, + { url = "https://files.pythonhosted.org/packages/45/7e/afe40eca3a2dc19b9904c0f5d7edfe82b5304cb831391edec0ac04af94c2/frozenlist-1.8.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:957e7c38f250991e48a9a73e6423db1bb9dd14e722a10f6b8bb8e16a0f55f695", size = 233160, upload-time = "2025-10-06T05:35:51.729Z" }, + { url = "https://files.pythonhosted.org/packages/a6/aa/7416eac95603ce428679d273255ffc7c998d4132cfae200103f164b108aa/frozenlist-1.8.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8585e3bb2cdea02fc88ffa245069c36555557ad3609e83be0ec71f54fd4abb52", size = 228544, upload-time = "2025-10-06T05:35:53.246Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3d/2a2d1f683d55ac7e3875e4263d28410063e738384d3adc294f5ff3d7105e/frozenlist-1.8.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:edee74874ce20a373d62dc28b0b18b93f645633c2943fd90ee9d898550770581", size = 243797, upload-time = "2025-10-06T05:35:54.497Z" }, + { url = "https://files.pythonhosted.org/packages/78/1e/2d5565b589e580c296d3bb54da08d206e797d941a83a6fdea42af23be79c/frozenlist-1.8.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c9a63152fe95756b85f31186bddf42e4c02c6321207fd6601a1c89ebac4fe567", size = 247923, upload-time = "2025-10-06T05:35:55.861Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/65872fcf1d326a7f101ad4d86285c403c87be7d832b7470b77f6d2ed5ddc/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6db2185db9be0a04fecf2f241c70b63b1a242e2805be291855078f2b404dd6b", size = 230886, upload-time = "2025-10-06T05:35:57.399Z" }, + { url = "https://files.pythonhosted.org/packages/a0/76/ac9ced601d62f6956f03cc794f9e04c81719509f85255abf96e2510f4265/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f4be2e3d8bc8aabd566f8d5b8ba7ecc09249d74ba3c9ed52e54dc23a293f0b92", size = 245731, upload-time = "2025-10-06T05:35:58.563Z" }, + { url = "https://files.pythonhosted.org/packages/b9/49/ecccb5f2598daf0b4a1415497eba4c33c1e8ce07495eb07d2860c731b8d5/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c8d1634419f39ea6f5c427ea2f90ca85126b54b50837f31497f3bf38266e853d", size = 241544, upload-time = "2025-10-06T05:35:59.719Z" }, + { url = "https://files.pythonhosted.org/packages/53/4b/ddf24113323c0bbcc54cb38c8b8916f1da7165e07b8e24a717b4a12cbf10/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:1a7fa382a4a223773ed64242dbe1c9c326ec09457e6b8428efb4118c685c3dfd", size = 241806, upload-time = "2025-10-06T05:36:00.959Z" }, + { url = "https://files.pythonhosted.org/packages/a7/fb/9b9a084d73c67175484ba2789a59f8eebebd0827d186a8102005ce41e1ba/frozenlist-1.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:11847b53d722050808926e785df837353bd4d75f1d494377e59b23594d834967", size = 229382, upload-time = "2025-10-06T05:36:02.22Z" }, + { url = "https://files.pythonhosted.org/packages/95/a3/c8fb25aac55bf5e12dae5c5aa6a98f85d436c1dc658f21c3ac73f9fa95e5/frozenlist-1.8.0-cp311-cp311-win32.whl", hash = "sha256:27c6e8077956cf73eadd514be8fb04d77fc946a7fe9f7fe167648b0b9085cc25", size = 39647, upload-time = "2025-10-06T05:36:03.409Z" }, + { url = "https://files.pythonhosted.org/packages/0a/f5/603d0d6a02cfd4c8f2a095a54672b3cf967ad688a60fb9faf04fc4887f65/frozenlist-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac913f8403b36a2c8610bbfd25b8013488533e71e62b4b4adce9c86c8cea905b", size = 44064, upload-time = "2025-10-06T05:36:04.368Z" }, + { url = "https://files.pythonhosted.org/packages/5d/16/c2c9ab44e181f043a86f9a8f84d5124b62dbcb3a02c0977ec72b9ac1d3e0/frozenlist-1.8.0-cp311-cp311-win_arm64.whl", hash = "sha256:d4d3214a0f8394edfa3e303136d0575eece0745ff2b47bd2cb2e66dd92d4351a", size = 39937, upload-time = "2025-10-06T05:36:05.669Z" }, + { url = "https://files.pythonhosted.org/packages/69/29/948b9aa87e75820a38650af445d2ef2b6b8a6fab1a23b6bb9e4ef0be2d59/frozenlist-1.8.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:78f7b9e5d6f2fdb88cdde9440dc147259b62b9d3b019924def9f6478be254ac1", size = 87782, upload-time = "2025-10-06T05:36:06.649Z" }, + { url = "https://files.pythonhosted.org/packages/64/80/4f6e318ee2a7c0750ed724fa33a4bdf1eacdc5a39a7a24e818a773cd91af/frozenlist-1.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:229bf37d2e4acdaf808fd3f06e854a4a7a3661e871b10dc1f8f1896a3b05f18b", size = 50594, upload-time = "2025-10-06T05:36:07.69Z" }, + { url = "https://files.pythonhosted.org/packages/2b/94/5c8a2b50a496b11dd519f4a24cb5496cf125681dd99e94c604ccdea9419a/frozenlist-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f833670942247a14eafbb675458b4e61c82e002a148f49e68257b79296e865c4", size = 50448, upload-time = "2025-10-06T05:36:08.78Z" }, + { url = "https://files.pythonhosted.org/packages/6a/bd/d91c5e39f490a49df14320f4e8c80161cfcce09f1e2cde1edd16a551abb3/frozenlist-1.8.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:494a5952b1c597ba44e0e78113a7266e656b9794eec897b19ead706bd7074383", size = 242411, upload-time = "2025-10-06T05:36:09.801Z" }, + { url = "https://files.pythonhosted.org/packages/8f/83/f61505a05109ef3293dfb1ff594d13d64a2324ac3482be2cedc2be818256/frozenlist-1.8.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f423a119f4777a4a056b66ce11527366a8bb92f54e541ade21f2374433f6d4", size = 243014, upload-time = "2025-10-06T05:36:11.394Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cb/cb6c7b0f7d4023ddda30cf56b8b17494eb3a79e3fda666bf735f63118b35/frozenlist-1.8.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3462dd9475af2025c31cc61be6652dfa25cbfb56cbbf52f4ccfe029f38decaf8", size = 234909, upload-time = "2025-10-06T05:36:12.598Z" }, + { url = "https://files.pythonhosted.org/packages/31/c5/cd7a1f3b8b34af009fb17d4123c5a778b44ae2804e3ad6b86204255f9ec5/frozenlist-1.8.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4c800524c9cd9bac5166cd6f55285957fcfc907db323e193f2afcd4d9abd69b", size = 250049, upload-time = "2025-10-06T05:36:14.065Z" }, + { url = "https://files.pythonhosted.org/packages/c0/01/2f95d3b416c584a1e7f0e1d6d31998c4a795f7544069ee2e0962a4b60740/frozenlist-1.8.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d6a5df73acd3399d893dafc71663ad22534b5aa4f94e8a2fabfe856c3c1b6a52", size = 256485, upload-time = "2025-10-06T05:36:15.39Z" }, + { url = "https://files.pythonhosted.org/packages/ce/03/024bf7720b3abaebcff6d0793d73c154237b85bdf67b7ed55e5e9596dc9a/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:405e8fe955c2280ce66428b3ca55e12b3c4e9c336fb2103a4937e891c69a4a29", size = 237619, upload-time = "2025-10-06T05:36:16.558Z" }, + { url = "https://files.pythonhosted.org/packages/69/fa/f8abdfe7d76b731f5d8bd217827cf6764d4f1d9763407e42717b4bed50a0/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:908bd3f6439f2fef9e85031b59fd4f1297af54415fb60e4254a95f75b3cab3f3", size = 250320, upload-time = "2025-10-06T05:36:17.821Z" }, + { url = "https://files.pythonhosted.org/packages/f5/3c/b051329f718b463b22613e269ad72138cc256c540f78a6de89452803a47d/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:294e487f9ec720bd8ffcebc99d575f7eff3568a08a253d1ee1a0378754b74143", size = 246820, upload-time = "2025-10-06T05:36:19.046Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ae/58282e8f98e444b3f4dd42448ff36fa38bef29e40d40f330b22e7108f565/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:74c51543498289c0c43656701be6b077f4b265868fa7f8a8859c197006efb608", size = 250518, upload-time = "2025-10-06T05:36:20.763Z" }, + { url = "https://files.pythonhosted.org/packages/8f/96/007e5944694d66123183845a106547a15944fbbb7154788cbf7272789536/frozenlist-1.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:776f352e8329135506a1d6bf16ac3f87bc25b28e765949282dcc627af36123aa", size = 239096, upload-time = "2025-10-06T05:36:22.129Z" }, + { url = "https://files.pythonhosted.org/packages/66/bb/852b9d6db2fa40be96f29c0d1205c306288f0684df8fd26ca1951d461a56/frozenlist-1.8.0-cp312-cp312-win32.whl", hash = "sha256:433403ae80709741ce34038da08511d4a77062aa924baf411ef73d1146e74faf", size = 39985, upload-time = "2025-10-06T05:36:23.661Z" }, + { url = "https://files.pythonhosted.org/packages/b8/af/38e51a553dd66eb064cdf193841f16f077585d4d28394c2fa6235cb41765/frozenlist-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:34187385b08f866104f0c0617404c8eb08165ab1272e884abc89c112e9c00746", size = 44591, upload-time = "2025-10-06T05:36:24.958Z" }, + { url = "https://files.pythonhosted.org/packages/a7/06/1dc65480ab147339fecc70797e9c2f69d9cea9cf38934ce08df070fdb9cb/frozenlist-1.8.0-cp312-cp312-win_arm64.whl", hash = "sha256:fe3c58d2f5db5fbd18c2987cba06d51b0529f52bc3a6cdc33d3f4eab725104bd", size = 40102, upload-time = "2025-10-06T05:36:26.333Z" }, + { url = "https://files.pythonhosted.org/packages/2d/40/0832c31a37d60f60ed79e9dfb5a92e1e2af4f40a16a29abcc7992af9edff/frozenlist-1.8.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8d92f1a84bb12d9e56f818b3a746f3efba93c1b63c8387a73dde655e1e42282a", size = 85717, upload-time = "2025-10-06T05:36:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/30/ba/b0b3de23f40bc55a7057bd38434e25c34fa48e17f20ee273bbde5e0650f3/frozenlist-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96153e77a591c8adc2ee805756c61f59fef4cf4073a9275ee86fe8cba41241f7", size = 49651, upload-time = "2025-10-06T05:36:28.855Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ab/6e5080ee374f875296c4243c381bbdef97a9ac39c6e3ce1d5f7d42cb78d6/frozenlist-1.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f21f00a91358803399890ab167098c131ec2ddd5f8f5fd5fe9c9f2c6fcd91e40", size = 49417, upload-time = "2025-10-06T05:36:29.877Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4e/e4691508f9477ce67da2015d8c00acd751e6287739123113a9fca6f1604e/frozenlist-1.8.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fb30f9626572a76dfe4293c7194a09fb1fe93ba94c7d4f720dfae3b646b45027", size = 234391, upload-time = "2025-10-06T05:36:31.301Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/c202df58e3acdf12969a7895fd6f3bc016c642e6726aa63bd3025e0fc71c/frozenlist-1.8.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eaa352d7047a31d87dafcacbabe89df0aa506abb5b1b85a2fb91bc3faa02d822", size = 233048, upload-time = "2025-10-06T05:36:32.531Z" }, + { url = "https://files.pythonhosted.org/packages/f9/c0/8746afb90f17b73ca5979c7a3958116e105ff796e718575175319b5bb4ce/frozenlist-1.8.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:03ae967b4e297f58f8c774c7eabcce57fe3c2434817d4385c50661845a058121", size = 226549, upload-time = "2025-10-06T05:36:33.706Z" }, + { url = "https://files.pythonhosted.org/packages/7e/eb/4c7eefc718ff72f9b6c4893291abaae5fbc0c82226a32dcd8ef4f7a5dbef/frozenlist-1.8.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f6292f1de555ffcc675941d65fffffb0a5bcd992905015f85d0592201793e0e5", size = 239833, upload-time = "2025-10-06T05:36:34.947Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/e5c02187cf704224f8b21bee886f3d713ca379535f16893233b9d672ea71/frozenlist-1.8.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29548f9b5b5e3460ce7378144c3010363d8035cea44bc0bf02d57f5a685e084e", size = 245363, upload-time = "2025-10-06T05:36:36.534Z" }, + { url = "https://files.pythonhosted.org/packages/1f/96/cb85ec608464472e82ad37a17f844889c36100eed57bea094518bf270692/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec3cc8c5d4084591b4237c0a272cc4f50a5b03396a47d9caaf76f5d7b38a4f11", size = 229314, upload-time = "2025-10-06T05:36:38.582Z" }, + { url = "https://files.pythonhosted.org/packages/5d/6f/4ae69c550e4cee66b57887daeebe006fe985917c01d0fff9caab9883f6d0/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:517279f58009d0b1f2e7c1b130b377a349405da3f7621ed6bfae50b10adf20c1", size = 243365, upload-time = "2025-10-06T05:36:40.152Z" }, + { url = "https://files.pythonhosted.org/packages/7a/58/afd56de246cf11780a40a2c28dc7cbabbf06337cc8ddb1c780a2d97e88d8/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db1e72ede2d0d7ccb213f218df6a078a9c09a7de257c2fe8fcef16d5925230b1", size = 237763, upload-time = "2025-10-06T05:36:41.355Z" }, + { url = "https://files.pythonhosted.org/packages/cb/36/cdfaf6ed42e2644740d4a10452d8e97fa1c062e2a8006e4b09f1b5fd7d63/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b4dec9482a65c54a5044486847b8a66bf10c9cb4926d42927ec4e8fd5db7fed8", size = 240110, upload-time = "2025-10-06T05:36:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/03/a8/9ea226fbefad669f11b52e864c55f0bd57d3c8d7eb07e9f2e9a0b39502e1/frozenlist-1.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:21900c48ae04d13d416f0e1e0c4d81f7931f73a9dfa0b7a8746fb2fe7dd970ed", size = 233717, upload-time = "2025-10-06T05:36:44.251Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0b/1b5531611e83ba7d13ccc9988967ea1b51186af64c42b7a7af465dcc9568/frozenlist-1.8.0-cp313-cp313-win32.whl", hash = "sha256:8b7b94a067d1c504ee0b16def57ad5738701e4ba10cec90529f13fa03c833496", size = 39628, upload-time = "2025-10-06T05:36:45.423Z" }, + { url = "https://files.pythonhosted.org/packages/d8/cf/174c91dbc9cc49bc7b7aab74d8b734e974d1faa8f191c74af9b7e80848e6/frozenlist-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:878be833caa6a3821caf85eb39c5ba92d28e85df26d57afb06b35b2efd937231", size = 43882, upload-time = "2025-10-06T05:36:46.796Z" }, + { url = "https://files.pythonhosted.org/packages/c1/17/502cd212cbfa96eb1388614fe39a3fc9ab87dbbe042b66f97acb57474834/frozenlist-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:44389d135b3ff43ba8cc89ff7f51f5a0bb6b63d829c8300f79a2fe4fe61bcc62", size = 39676, upload-time = "2025-10-06T05:36:47.8Z" }, + { url = "https://files.pythonhosted.org/packages/d2/5c/3bbfaa920dfab09e76946a5d2833a7cbdf7b9b4a91c714666ac4855b88b4/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e25ac20a2ef37e91c1b39938b591457666a0fa835c7783c3a8f33ea42870db94", size = 89235, upload-time = "2025-10-06T05:36:48.78Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d6/f03961ef72166cec1687e84e8925838442b615bd0b8854b54923ce5b7b8a/frozenlist-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07cdca25a91a4386d2e76ad992916a85038a9b97561bf7a3fd12d5d9ce31870c", size = 50742, upload-time = "2025-10-06T05:36:49.837Z" }, + { url = "https://files.pythonhosted.org/packages/1e/bb/a6d12b7ba4c3337667d0e421f7181c82dda448ce4e7ad7ecd249a16fa806/frozenlist-1.8.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e0c11f2cc6717e0a741f84a527c52616140741cd812a50422f83dc31749fb52", size = 51725, upload-time = "2025-10-06T05:36:50.851Z" }, + { url = "https://files.pythonhosted.org/packages/bc/71/d1fed0ffe2c2ccd70b43714c6cab0f4188f09f8a67a7914a6b46ee30f274/frozenlist-1.8.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b3210649ee28062ea6099cfda39e147fa1bc039583c8ee4481cb7811e2448c51", size = 284533, upload-time = "2025-10-06T05:36:51.898Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/fb1685a7b009d89f9bf78a42d94461bc06581f6e718c39344754a5d9bada/frozenlist-1.8.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:581ef5194c48035a7de2aefc72ac6539823bb71508189e5de01d60c9dcd5fa65", size = 292506, upload-time = "2025-10-06T05:36:53.101Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3b/b991fe1612703f7e0d05c0cf734c1b77aaf7c7d321df4572e8d36e7048c8/frozenlist-1.8.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3ef2d026f16a2b1866e1d86fc4e1291e1ed8a387b2c333809419a2f8b3a77b82", size = 274161, upload-time = "2025-10-06T05:36:54.309Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ec/c5c618767bcdf66e88945ec0157d7f6c4a1322f1473392319b7a2501ded7/frozenlist-1.8.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5500ef82073f599ac84d888e3a8c1f77ac831183244bfd7f11eaa0289fb30714", size = 294676, upload-time = "2025-10-06T05:36:55.566Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ce/3934758637d8f8a88d11f0585d6495ef54b2044ed6ec84492a91fa3b27aa/frozenlist-1.8.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50066c3997d0091c411a66e710f4e11752251e6d2d73d70d8d5d4c76442a199d", size = 300638, upload-time = "2025-10-06T05:36:56.758Z" }, + { url = "https://files.pythonhosted.org/packages/fc/4f/a7e4d0d467298f42de4b41cbc7ddaf19d3cfeabaf9ff97c20c6c7ee409f9/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5c1c8e78426e59b3f8005e9b19f6ff46e5845895adbde20ece9218319eca6506", size = 283067, upload-time = "2025-10-06T05:36:57.965Z" }, + { url = "https://files.pythonhosted.org/packages/dc/48/c7b163063d55a83772b268e6d1affb960771b0e203b632cfe09522d67ea5/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:eefdba20de0d938cec6a89bd4d70f346a03108a19b9df4248d3cf0d88f1b0f51", size = 292101, upload-time = "2025-10-06T05:36:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d0/2366d3c4ecdc2fd391e0afa6e11500bfba0ea772764d631bbf82f0136c9d/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cf253e0e1c3ceb4aaff6df637ce033ff6535fb8c70a764a8f46aafd3d6ab798e", size = 289901, upload-time = "2025-10-06T05:37:00.811Z" }, + { url = "https://files.pythonhosted.org/packages/b8/94/daff920e82c1b70e3618a2ac39fbc01ae3e2ff6124e80739ce5d71c9b920/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:032efa2674356903cd0261c4317a561a6850f3ac864a63fc1583147fb05a79b0", size = 289395, upload-time = "2025-10-06T05:37:02.115Z" }, + { url = "https://files.pythonhosted.org/packages/e3/20/bba307ab4235a09fdcd3cc5508dbabd17c4634a1af4b96e0f69bfe551ebd/frozenlist-1.8.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6da155091429aeba16851ecb10a9104a108bcd32f6c1642867eadaee401c1c41", size = 283659, upload-time = "2025-10-06T05:37:03.711Z" }, + { url = "https://files.pythonhosted.org/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b", size = 43492, upload-time = "2025-10-06T05:37:04.915Z" }, + { url = "https://files.pythonhosted.org/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888", size = 48034, upload-time = "2025-10-06T05:37:06.343Z" }, + { url = "https://files.pythonhosted.org/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042", size = 41749, upload-time = "2025-10-06T05:37:07.431Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", size = 86127, upload-time = "2025-10-06T05:37:08.438Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", size = 49698, upload-time = "2025-10-06T05:37:09.48Z" }, + { url = "https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", size = 49749, upload-time = "2025-10-06T05:37:10.569Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", size = 231298, upload-time = "2025-10-06T05:37:11.993Z" }, + { url = "https://files.pythonhosted.org/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", size = 232015, upload-time = "2025-10-06T05:37:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", size = 225038, upload-time = "2025-10-06T05:37:14.577Z" }, + { url = "https://files.pythonhosted.org/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", size = 240130, upload-time = "2025-10-06T05:37:15.781Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", size = 242845, upload-time = "2025-10-06T05:37:17.037Z" }, + { url = "https://files.pythonhosted.org/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", size = 229131, upload-time = "2025-10-06T05:37:18.221Z" }, + { url = "https://files.pythonhosted.org/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", size = 240542, upload-time = "2025-10-06T05:37:19.771Z" }, + { url = "https://files.pythonhosted.org/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", size = 237308, upload-time = "2025-10-06T05:37:20.969Z" }, + { url = "https://files.pythonhosted.org/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", size = 238210, upload-time = "2025-10-06T05:37:22.252Z" }, + { url = "https://files.pythonhosted.org/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", size = 231972, upload-time = "2025-10-06T05:37:23.5Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", size = 40536, upload-time = "2025-10-06T05:37:25.581Z" }, + { url = "https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", size = 44330, upload-time = "2025-10-06T05:37:26.928Z" }, + { url = "https://files.pythonhosted.org/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", size = 40627, upload-time = "2025-10-06T05:37:28.075Z" }, + { url = "https://files.pythonhosted.org/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", size = 89238, upload-time = "2025-10-06T05:37:29.373Z" }, + { url = "https://files.pythonhosted.org/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", size = 50738, upload-time = "2025-10-06T05:37:30.792Z" }, + { url = "https://files.pythonhosted.org/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", size = 51739, upload-time = "2025-10-06T05:37:32.127Z" }, + { url = "https://files.pythonhosted.org/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", size = 284186, upload-time = "2025-10-06T05:37:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", size = 292196, upload-time = "2025-10-06T05:37:36.107Z" }, + { url = "https://files.pythonhosted.org/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", size = 273830, upload-time = "2025-10-06T05:37:37.663Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", size = 294289, upload-time = "2025-10-06T05:37:39.261Z" }, + { url = "https://files.pythonhosted.org/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", size = 300318, upload-time = "2025-10-06T05:37:43.213Z" }, + { url = "https://files.pythonhosted.org/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", size = 282814, upload-time = "2025-10-06T05:37:45.337Z" }, + { url = "https://files.pythonhosted.org/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", size = 291762, upload-time = "2025-10-06T05:37:46.657Z" }, + { url = "https://files.pythonhosted.org/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", size = 289470, upload-time = "2025-10-06T05:37:47.946Z" }, + { url = "https://files.pythonhosted.org/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", size = 289042, upload-time = "2025-10-06T05:37:49.499Z" }, + { url = "https://files.pythonhosted.org/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", size = 283148, upload-time = "2025-10-06T05:37:50.745Z" }, + { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" }, + { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, +] + +[[package]] +name = "fsspec" +version = "2025.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/de/e0/bab50af11c2d75c9c4a2a26a5254573c0bd97cea152254401510950486fa/fsspec-2025.9.0.tar.gz", hash = "sha256:19fd429483d25d28b65ec68f9f4adc16c17ea2c7c7bf54ec61360d478fb19c19", size = 304847, upload-time = "2025-09-02T19:10:49.215Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/71/70db47e4f6ce3e5c37a607355f80da8860a33226be640226ac52cb05ef2e/fsspec-2025.9.0-py3-none-any.whl", hash = "sha256:530dc2a2af60a414a832059574df4a6e10cce927f6f4a78209390fe38955cfb7", size = 199289, upload-time = "2025-09-02T19:10:47.708Z" }, +] + +[package.optional-dependencies] +http = [ + { name = "aiohttp" }, +] + +[[package]] +name = "ftfy" +version = "6.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a5/d3/8650919bc3c7c6e90ee3fa7fd618bf373cbbe55dff043bd67353dbb20cd8/ftfy-6.3.1.tar.gz", hash = "sha256:9b3c3d90f84fb267fe64d375a07b7f8912d817cf86009ae134aa03e1819506ec", size = 308927, upload-time = "2024-10-26T00:50:35.149Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/6e/81d47999aebc1b155f81eca4477a616a70f238a2549848c38983f3c22a82/ftfy-6.3.1-py3-none-any.whl", hash = "sha256:7c70eb532015cd2f9adb53f101fb6c7945988d023a085d127d1573dc49dd0083", size = 44821, upload-time = "2024-10-26T00:50:33.425Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "huggingface-hub" +version = "0.31.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "fsspec" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/7b/09ab792c463975fcd0a81f459b5e900057dabbbc274ff253bb28d58ebfce/huggingface_hub-0.31.2.tar.gz", hash = "sha256:7053561376ed7f6ffdaecf09cc54d70dc784ac6315fa4bb9b93e19662b029675", size = 403025, upload-time = "2025-05-13T09:45:43.617Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/81/a8fd9c226f7e3bc8918f1e456131717cb38e93f18ccc109bf3c8471e464f/huggingface_hub-0.31.2-py3-none-any.whl", hash = "sha256:8138cd52aa2326b4429bb00a4a1ba8538346b7b8a808cdce30acb6f1f1bdaeec", size = 484230, upload-time = "2025-05-13T09:45:41.977Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "joblib" +version = "1.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/5d/447af5ea094b9e4c4054f82e223ada074c552335b9b4b2d14bd9b35a67c4/joblib-1.5.2.tar.gz", hash = "sha256:3faa5c39054b2f03ca547da9b2f52fde67c06240c31853f306aea97f13647b55", size = 331077, upload-time = "2025-08-27T12:15:46.575Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/e8/685f47e0d754320684db4425a0967f7d3fa70126bffd76110b7009a0090f/joblib-1.5.2-py3-none-any.whl", hash = "sha256:4e1f0bdbb987e6d843c70cf43714cb276623def372df3c22fe5266b2670bc241", size = 308396, upload-time = "2025-08-27T12:15:45.188Z" }, +] + +[[package]] +name = "kiwisolver" +version = "1.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/3c/85844f1b0feb11ee581ac23fe5fce65cd049a200c1446708cc1b7f922875/kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d", size = 97564, upload-time = "2025-08-10T21:27:49.279Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/5d/8ce64e36d4e3aac5ca96996457dcf33e34e6051492399a3f1fec5657f30b/kiwisolver-1.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b4b4d74bda2b8ebf4da5bd42af11d02d04428b2c32846e4c2c93219df8a7987b", size = 124159, upload-time = "2025-08-10T21:25:35.472Z" }, + { url = "https://files.pythonhosted.org/packages/96/1e/22f63ec454874378175a5f435d6ea1363dd33fb2af832c6643e4ccea0dc8/kiwisolver-1.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fb3b8132019ea572f4611d770991000d7f58127560c4889729248eb5852a102f", size = 66578, upload-time = "2025-08-10T21:25:36.73Z" }, + { url = "https://files.pythonhosted.org/packages/41/4c/1925dcfff47a02d465121967b95151c82d11027d5ec5242771e580e731bd/kiwisolver-1.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84fd60810829c27ae375114cd379da1fa65e6918e1da405f356a775d49a62bcf", size = 65312, upload-time = "2025-08-10T21:25:37.658Z" }, + { url = "https://files.pythonhosted.org/packages/d4/42/0f333164e6307a0687d1eb9ad256215aae2f4bd5d28f4653d6cd319a3ba3/kiwisolver-1.4.9-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b78efa4c6e804ecdf727e580dbb9cba85624d2e1c6b5cb059c66290063bd99a9", size = 1628458, upload-time = "2025-08-10T21:25:39.067Z" }, + { url = "https://files.pythonhosted.org/packages/86/b6/2dccb977d651943995a90bfe3495c2ab2ba5cd77093d9f2318a20c9a6f59/kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4efec7bcf21671db6a3294ff301d2fc861c31faa3c8740d1a94689234d1b415", size = 1225640, upload-time = "2025-08-10T21:25:40.489Z" }, + { url = "https://files.pythonhosted.org/packages/50/2b/362ebd3eec46c850ccf2bfe3e30f2fc4c008750011f38a850f088c56a1c6/kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90f47e70293fc3688b71271100a1a5453aa9944a81d27ff779c108372cf5567b", size = 1244074, upload-time = "2025-08-10T21:25:42.221Z" }, + { url = "https://files.pythonhosted.org/packages/6f/bb/f09a1e66dab8984773d13184a10a29fe67125337649d26bdef547024ed6b/kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fdca1def57a2e88ef339de1737a1449d6dbf5fab184c54a1fca01d541317154", size = 1293036, upload-time = "2025-08-10T21:25:43.801Z" }, + { url = "https://files.pythonhosted.org/packages/ea/01/11ecf892f201cafda0f68fa59212edaea93e96c37884b747c181303fccd1/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9cf554f21be770f5111a1690d42313e140355e687e05cf82cb23d0a721a64a48", size = 2175310, upload-time = "2025-08-10T21:25:45.045Z" }, + { url = "https://files.pythonhosted.org/packages/7f/5f/bfe11d5b934f500cc004314819ea92427e6e5462706a498c1d4fc052e08f/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fc1795ac5cd0510207482c3d1d3ed781143383b8cfd36f5c645f3897ce066220", size = 2270943, upload-time = "2025-08-10T21:25:46.393Z" }, + { url = "https://files.pythonhosted.org/packages/3d/de/259f786bf71f1e03e73d87e2db1a9a3bcab64d7b4fd780167123161630ad/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ccd09f20ccdbbd341b21a67ab50a119b64a403b09288c27481575105283c1586", size = 2440488, upload-time = "2025-08-10T21:25:48.074Z" }, + { url = "https://files.pythonhosted.org/packages/1b/76/c989c278faf037c4d3421ec07a5c452cd3e09545d6dae7f87c15f54e4edf/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:540c7c72324d864406a009d72f5d6856f49693db95d1fbb46cf86febef873634", size = 2246787, upload-time = "2025-08-10T21:25:49.442Z" }, + { url = "https://files.pythonhosted.org/packages/a2/55/c2898d84ca440852e560ca9f2a0d28e6e931ac0849b896d77231929900e7/kiwisolver-1.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:ede8c6d533bc6601a47ad4046080d36b8fc99f81e6f1c17b0ac3c2dc91ac7611", size = 73730, upload-time = "2025-08-10T21:25:51.102Z" }, + { url = "https://files.pythonhosted.org/packages/e8/09/486d6ac523dd33b80b368247f238125d027964cfacb45c654841e88fb2ae/kiwisolver-1.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:7b4da0d01ac866a57dd61ac258c5607b4cd677f63abaec7b148354d2b2cdd536", size = 65036, upload-time = "2025-08-10T21:25:52.063Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ab/c80b0d5a9d8a1a65f4f815f2afff9798b12c3b9f31f1d304dd233dd920e2/kiwisolver-1.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb14a5da6dc7642b0f3a18f13654847cd8b7a2550e2645a5bda677862b03ba16", size = 124167, upload-time = "2025-08-10T21:25:53.403Z" }, + { url = "https://files.pythonhosted.org/packages/a0/c0/27fe1a68a39cf62472a300e2879ffc13c0538546c359b86f149cc19f6ac3/kiwisolver-1.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39a219e1c81ae3b103643d2aedb90f1ef22650deb266ff12a19e7773f3e5f089", size = 66579, upload-time = "2025-08-10T21:25:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/31/a2/a12a503ac1fd4943c50f9822678e8015a790a13b5490354c68afb8489814/kiwisolver-1.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2405a7d98604b87f3fc28b1716783534b1b4b8510d8142adca34ee0bc3c87543", size = 65309, upload-time = "2025-08-10T21:25:55.76Z" }, + { url = "https://files.pythonhosted.org/packages/66/e1/e533435c0be77c3f64040d68d7a657771194a63c279f55573188161e81ca/kiwisolver-1.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dc1ae486f9abcef254b5618dfb4113dd49f94c68e3e027d03cf0143f3f772b61", size = 1435596, upload-time = "2025-08-10T21:25:56.861Z" }, + { url = "https://files.pythonhosted.org/packages/67/1e/51b73c7347f9aabdc7215aa79e8b15299097dc2f8e67dee2b095faca9cb0/kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a1f570ce4d62d718dce3f179ee78dac3b545ac16c0c04bb363b7607a949c0d1", size = 1246548, upload-time = "2025-08-10T21:25:58.246Z" }, + { url = "https://files.pythonhosted.org/packages/21/aa/72a1c5d1e430294f2d32adb9542719cfb441b5da368d09d268c7757af46c/kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb27e7b78d716c591e88e0a09a2139c6577865d7f2e152488c2cc6257f460872", size = 1263618, upload-time = "2025-08-10T21:25:59.857Z" }, + { url = "https://files.pythonhosted.org/packages/a3/af/db1509a9e79dbf4c260ce0cfa3903ea8945f6240e9e59d1e4deb731b1a40/kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:15163165efc2f627eb9687ea5f3a28137217d217ac4024893d753f46bce9de26", size = 1317437, upload-time = "2025-08-10T21:26:01.105Z" }, + { url = "https://files.pythonhosted.org/packages/e0/f2/3ea5ee5d52abacdd12013a94130436e19969fa183faa1e7c7fbc89e9a42f/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bdee92c56a71d2b24c33a7d4c2856bd6419d017e08caa7802d2963870e315028", size = 2195742, upload-time = "2025-08-10T21:26:02.675Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9b/1efdd3013c2d9a2566aa6a337e9923a00590c516add9a1e89a768a3eb2fc/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:412f287c55a6f54b0650bd9b6dce5aceddb95864a1a90c87af16979d37c89771", size = 2290810, upload-time = "2025-08-10T21:26:04.009Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e5/cfdc36109ae4e67361f9bc5b41323648cb24a01b9ade18784657e022e65f/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2c93f00dcba2eea70af2be5f11a830a742fe6b579a1d4e00f47760ef13be247a", size = 2461579, upload-time = "2025-08-10T21:26:05.317Z" }, + { url = "https://files.pythonhosted.org/packages/62/86/b589e5e86c7610842213994cdea5add00960076bef4ae290c5fa68589cac/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f117e1a089d9411663a3207ba874f31be9ac8eaa5b533787024dc07aeb74f464", size = 2268071, upload-time = "2025-08-10T21:26:06.686Z" }, + { url = "https://files.pythonhosted.org/packages/3b/c6/f8df8509fd1eee6c622febe54384a96cfaf4d43bf2ccec7a0cc17e4715c9/kiwisolver-1.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:be6a04e6c79819c9a8c2373317d19a96048e5a3f90bec587787e86a1153883c2", size = 73840, upload-time = "2025-08-10T21:26:07.94Z" }, + { url = "https://files.pythonhosted.org/packages/e2/2d/16e0581daafd147bc11ac53f032a2b45eabac897f42a338d0a13c1e5c436/kiwisolver-1.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:0ae37737256ba2de764ddc12aed4956460277f00c4996d51a197e72f62f5eec7", size = 65159, upload-time = "2025-08-10T21:26:09.048Z" }, + { url = "https://files.pythonhosted.org/packages/86/c9/13573a747838aeb1c76e3267620daa054f4152444d1f3d1a2324b78255b5/kiwisolver-1.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ac5a486ac389dddcc5bef4f365b6ae3ffff2c433324fb38dd35e3fab7c957999", size = 123686, upload-time = "2025-08-10T21:26:10.034Z" }, + { url = "https://files.pythonhosted.org/packages/51/ea/2ecf727927f103ffd1739271ca19c424d0e65ea473fbaeea1c014aea93f6/kiwisolver-1.4.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2ba92255faa7309d06fe44c3a4a97efe1c8d640c2a79a5ef728b685762a6fd2", size = 66460, upload-time = "2025-08-10T21:26:11.083Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5a/51f5464373ce2aeb5194508298a508b6f21d3867f499556263c64c621914/kiwisolver-1.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a2899935e724dd1074cb568ce7ac0dce28b2cd6ab539c8e001a8578eb106d14", size = 64952, upload-time = "2025-08-10T21:26:12.058Z" }, + { url = "https://files.pythonhosted.org/packages/70/90/6d240beb0f24b74371762873e9b7f499f1e02166a2d9c5801f4dbf8fa12e/kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f6008a4919fdbc0b0097089f67a1eb55d950ed7e90ce2cc3e640abadd2757a04", size = 1474756, upload-time = "2025-08-10T21:26:13.096Z" }, + { url = "https://files.pythonhosted.org/packages/12/42/f36816eaf465220f683fb711efdd1bbf7a7005a2473d0e4ed421389bd26c/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67bb8b474b4181770f926f7b7d2f8c0248cbcb78b660fdd41a47054b28d2a752", size = 1276404, upload-time = "2025-08-10T21:26:14.457Z" }, + { url = "https://files.pythonhosted.org/packages/2e/64/bc2de94800adc830c476dce44e9b40fd0809cddeef1fde9fcf0f73da301f/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2327a4a30d3ee07d2fbe2e7933e8a37c591663b96ce42a00bc67461a87d7df77", size = 1294410, upload-time = "2025-08-10T21:26:15.73Z" }, + { url = "https://files.pythonhosted.org/packages/5f/42/2dc82330a70aa8e55b6d395b11018045e58d0bb00834502bf11509f79091/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a08b491ec91b1d5053ac177afe5290adacf1f0f6307d771ccac5de30592d198", size = 1343631, upload-time = "2025-08-10T21:26:17.045Z" }, + { url = "https://files.pythonhosted.org/packages/22/fd/f4c67a6ed1aab149ec5a8a401c323cee7a1cbe364381bb6c9c0d564e0e20/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8fc5c867c22b828001b6a38d2eaeb88160bf5783c6cb4a5e440efc981ce286d", size = 2224963, upload-time = "2025-08-10T21:26:18.737Z" }, + { url = "https://files.pythonhosted.org/packages/45/aa/76720bd4cb3713314677d9ec94dcc21ced3f1baf4830adde5bb9b2430a5f/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3b3115b2581ea35bb6d1f24a4c90af37e5d9b49dcff267eeed14c3893c5b86ab", size = 2321295, upload-time = "2025-08-10T21:26:20.11Z" }, + { url = "https://files.pythonhosted.org/packages/80/19/d3ec0d9ab711242f56ae0dc2fc5d70e298bb4a1f9dfab44c027668c673a1/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858e4c22fb075920b96a291928cb7dea5644e94c0ee4fcd5af7e865655e4ccf2", size = 2487987, upload-time = "2025-08-10T21:26:21.49Z" }, + { url = "https://files.pythonhosted.org/packages/39/e9/61e4813b2c97e86b6fdbd4dd824bf72d28bcd8d4849b8084a357bc0dd64d/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed0fecd28cc62c54b262e3736f8bb2512d8dcfdc2bcf08be5f47f96bf405b145", size = 2291817, upload-time = "2025-08-10T21:26:22.812Z" }, + { url = "https://files.pythonhosted.org/packages/a0/41/85d82b0291db7504da3c2defe35c9a8a5c9803a730f297bd823d11d5fb77/kiwisolver-1.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:f68208a520c3d86ea51acf688a3e3002615a7f0238002cccc17affecc86a8a54", size = 73895, upload-time = "2025-08-10T21:26:24.37Z" }, + { url = "https://files.pythonhosted.org/packages/e2/92/5f3068cf15ee5cb624a0c7596e67e2a0bb2adee33f71c379054a491d07da/kiwisolver-1.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:2c1a4f57df73965f3f14df20b80ee29e6a7930a57d2d9e8491a25f676e197c60", size = 64992, upload-time = "2025-08-10T21:26:25.732Z" }, + { url = "https://files.pythonhosted.org/packages/31/c1/c2686cda909742ab66c7388e9a1a8521a59eb89f8bcfbee28fc980d07e24/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8", size = 123681, upload-time = "2025-08-10T21:26:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/ca/f0/f44f50c9f5b1a1860261092e3bc91ecdc9acda848a8b8c6abfda4a24dd5c/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2", size = 66464, upload-time = "2025-08-10T21:26:27.733Z" }, + { url = "https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f", size = 64961, upload-time = "2025-08-10T21:26:28.729Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098", size = 1474607, upload-time = "2025-08-10T21:26:29.798Z" }, + { url = "https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed", size = 1276546, upload-time = "2025-08-10T21:26:31.401Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ad/8bfc1c93d4cc565e5069162f610ba2f48ff39b7de4b5b8d93f69f30c4bed/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525", size = 1294482, upload-time = "2025-08-10T21:26:32.721Z" }, + { url = "https://files.pythonhosted.org/packages/da/f1/6aca55ff798901d8ce403206d00e033191f63d82dd708a186e0ed2067e9c/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78", size = 1343720, upload-time = "2025-08-10T21:26:34.032Z" }, + { url = "https://files.pythonhosted.org/packages/d1/91/eed031876c595c81d90d0f6fc681ece250e14bf6998c3d7c419466b523b7/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b", size = 2224907, upload-time = "2025-08-10T21:26:35.824Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ec/4d1925f2e49617b9cca9c34bfa11adefad49d00db038e692a559454dfb2e/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799", size = 2321334, upload-time = "2025-08-10T21:26:37.534Z" }, + { url = "https://files.pythonhosted.org/packages/43/cb/450cd4499356f68802750c6ddc18647b8ea01ffa28f50d20598e0befe6e9/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3", size = 2488313, upload-time = "2025-08-10T21:26:39.191Z" }, + { url = "https://files.pythonhosted.org/packages/71/67/fc76242bd99f885651128a5d4fa6083e5524694b7c88b489b1b55fdc491d/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c", size = 2291970, upload-time = "2025-08-10T21:26:40.828Z" }, + { url = "https://files.pythonhosted.org/packages/75/bd/f1a5d894000941739f2ae1b65a32892349423ad49c2e6d0771d0bad3fae4/kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d", size = 73894, upload-time = "2025-08-10T21:26:42.33Z" }, + { url = "https://files.pythonhosted.org/packages/95/38/dce480814d25b99a391abbddadc78f7c117c6da34be68ca8b02d5848b424/kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2", size = 64995, upload-time = "2025-08-10T21:26:43.889Z" }, + { url = "https://files.pythonhosted.org/packages/e2/37/7d218ce5d92dadc5ebdd9070d903e0c7cf7edfe03f179433ac4d13ce659c/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1", size = 126510, upload-time = "2025-08-10T21:26:44.915Z" }, + { url = "https://files.pythonhosted.org/packages/23/b0/e85a2b48233daef4b648fb657ebbb6f8367696a2d9548a00b4ee0eb67803/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1", size = 67903, upload-time = "2025-08-10T21:26:45.934Z" }, + { url = "https://files.pythonhosted.org/packages/44/98/f2425bc0113ad7de24da6bb4dae1343476e95e1d738be7c04d31a5d037fd/kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11", size = 66402, upload-time = "2025-08-10T21:26:47.101Z" }, + { url = "https://files.pythonhosted.org/packages/98/d8/594657886df9f34c4177cc353cc28ca7e6e5eb562d37ccc233bff43bbe2a/kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c", size = 1582135, upload-time = "2025-08-10T21:26:48.665Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c6/38a115b7170f8b306fc929e166340c24958347308ea3012c2b44e7e295db/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197", size = 1389409, upload-time = "2025-08-10T21:26:50.335Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3b/e04883dace81f24a568bcee6eb3001da4ba05114afa622ec9b6fafdc1f5e/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c", size = 1401763, upload-time = "2025-08-10T21:26:51.867Z" }, + { url = "https://files.pythonhosted.org/packages/9f/80/20ace48e33408947af49d7d15c341eaee69e4e0304aab4b7660e234d6288/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185", size = 1453643, upload-time = "2025-08-10T21:26:53.592Z" }, + { url = "https://files.pythonhosted.org/packages/64/31/6ce4380a4cd1f515bdda976a1e90e547ccd47b67a1546d63884463c92ca9/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748", size = 2330818, upload-time = "2025-08-10T21:26:55.051Z" }, + { url = "https://files.pythonhosted.org/packages/fa/e9/3f3fcba3bcc7432c795b82646306e822f3fd74df0ee81f0fa067a1f95668/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64", size = 2419963, upload-time = "2025-08-10T21:26:56.421Z" }, + { url = "https://files.pythonhosted.org/packages/99/43/7320c50e4133575c66e9f7dadead35ab22d7c012a3b09bb35647792b2a6d/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff", size = 2594639, upload-time = "2025-08-10T21:26:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/65/d6/17ae4a270d4a987ef8a385b906d2bdfc9fce502d6dc0d3aea865b47f548c/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07", size = 2391741, upload-time = "2025-08-10T21:26:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/2a/8f/8f6f491d595a9e5912971f3f863d81baddccc8a4d0c3749d6a0dd9ffc9df/kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c", size = 68646, upload-time = "2025-08-10T21:27:00.52Z" }, + { url = "https://files.pythonhosted.org/packages/6b/32/6cc0fbc9c54d06c2969faa9c1d29f5751a2e51809dd55c69055e62d9b426/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386", size = 123806, upload-time = "2025-08-10T21:27:01.537Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/2bfb1d4a4823d92e8cbb420fe024b8d2167f72079b3bb941207c42570bdf/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552", size = 66605, upload-time = "2025-08-10T21:27:03.335Z" }, + { url = "https://files.pythonhosted.org/packages/f7/69/00aafdb4e4509c2ca6064646cba9cd4b37933898f426756adb2cb92ebbed/kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3", size = 64925, upload-time = "2025-08-10T21:27:04.339Z" }, + { url = "https://files.pythonhosted.org/packages/43/dc/51acc6791aa14e5cb6d8a2e28cefb0dc2886d8862795449d021334c0df20/kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58", size = 1472414, upload-time = "2025-08-10T21:27:05.437Z" }, + { url = "https://files.pythonhosted.org/packages/3d/bb/93fa64a81db304ac8a246f834d5094fae4b13baf53c839d6bb6e81177129/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4", size = 1281272, upload-time = "2025-08-10T21:27:07.063Z" }, + { url = "https://files.pythonhosted.org/packages/70/e6/6df102916960fb8d05069d4bd92d6d9a8202d5a3e2444494e7cd50f65b7a/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df", size = 1298578, upload-time = "2025-08-10T21:27:08.452Z" }, + { url = "https://files.pythonhosted.org/packages/7c/47/e142aaa612f5343736b087864dbaebc53ea8831453fb47e7521fa8658f30/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6", size = 1345607, upload-time = "2025-08-10T21:27:10.125Z" }, + { url = "https://files.pythonhosted.org/packages/54/89/d641a746194a0f4d1a3670fb900d0dbaa786fb98341056814bc3f058fa52/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5", size = 2230150, upload-time = "2025-08-10T21:27:11.484Z" }, + { url = "https://files.pythonhosted.org/packages/aa/6b/5ee1207198febdf16ac11f78c5ae40861b809cbe0e6d2a8d5b0b3044b199/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf", size = 2325979, upload-time = "2025-08-10T21:27:12.917Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ff/b269eefd90f4ae14dcc74973d5a0f6d28d3b9bb1afd8c0340513afe6b39a/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5", size = 2491456, upload-time = "2025-08-10T21:27:14.353Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d4/10303190bd4d30de547534601e259a4fbf014eed94aae3e5521129215086/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce", size = 2294621, upload-time = "2025-08-10T21:27:15.808Z" }, + { url = "https://files.pythonhosted.org/packages/28/e0/a9a90416fce5c0be25742729c2ea52105d62eda6c4be4d803c2a7be1fa50/kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7", size = 75417, upload-time = "2025-08-10T21:27:17.436Z" }, + { url = "https://files.pythonhosted.org/packages/1f/10/6949958215b7a9a264299a7db195564e87900f709db9245e4ebdd3c70779/kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c", size = 66582, upload-time = "2025-08-10T21:27:18.436Z" }, + { url = "https://files.pythonhosted.org/packages/ec/79/60e53067903d3bc5469b369fe0dfc6b3482e2133e85dae9daa9527535991/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548", size = 126514, upload-time = "2025-08-10T21:27:19.465Z" }, + { url = "https://files.pythonhosted.org/packages/25/d1/4843d3e8d46b072c12a38c97c57fab4608d36e13fe47d47ee96b4d61ba6f/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d", size = 67905, upload-time = "2025-08-10T21:27:20.51Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c", size = 66399, upload-time = "2025-08-10T21:27:21.496Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122", size = 1582197, upload-time = "2025-08-10T21:27:22.604Z" }, + { url = "https://files.pythonhosted.org/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64", size = 1390125, upload-time = "2025-08-10T21:27:24.036Z" }, + { url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" }, + { url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" }, + { url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" }, + { url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" }, + { url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" }, + { url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" }, + { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, + { url = "https://files.pythonhosted.org/packages/a2/63/fde392691690f55b38d5dd7b3710f5353bf7a8e52de93a22968801ab8978/kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4d1d9e582ad4d63062d34077a9a1e9f3c34088a2ec5135b1f7190c07cf366527", size = 60183, upload-time = "2025-08-10T21:27:37.669Z" }, + { url = "https://files.pythonhosted.org/packages/27/b1/6aad34edfdb7cced27f371866f211332bba215bfd918ad3322a58f480d8b/kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:deed0c7258ceb4c44ad5ec7d9918f9f14fd05b2be86378d86cf50e63d1e7b771", size = 58675, upload-time = "2025-08-10T21:27:39.031Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1a/23d855a702bb35a76faed5ae2ba3de57d323f48b1f6b17ee2176c4849463/kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a590506f303f512dff6b7f75fd2fd18e16943efee932008fe7140e5fa91d80e", size = 80277, upload-time = "2025-08-10T21:27:40.129Z" }, + { url = "https://files.pythonhosted.org/packages/5a/5b/5239e3c2b8fb5afa1e8508f721bb77325f740ab6994d963e61b2b7abcc1e/kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e09c2279a4d01f099f52d5c4b3d9e208e91edcbd1a175c9662a8b16e000fece9", size = 77994, upload-time = "2025-08-10T21:27:41.181Z" }, + { url = "https://files.pythonhosted.org/packages/f9/1c/5d4d468fb16f8410e596ed0eac02d2c68752aa7dc92997fe9d60a7147665/kiwisolver-1.4.9-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c9e7cdf45d594ee04d5be1b24dd9d49f3d1590959b2271fb30b5ca2b262c00fb", size = 73744, upload-time = "2025-08-10T21:27:42.254Z" }, + { url = "https://files.pythonhosted.org/packages/a3/0f/36d89194b5a32c054ce93e586d4049b6c2c22887b0eb229c61c68afd3078/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5", size = 60104, upload-time = "2025-08-10T21:27:43.287Z" }, + { url = "https://files.pythonhosted.org/packages/52/ba/4ed75f59e4658fd21fe7dde1fee0ac397c678ec3befba3fe6482d987af87/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa", size = 58592, upload-time = "2025-08-10T21:27:44.314Z" }, + { url = "https://files.pythonhosted.org/packages/33/01/a8ea7c5ea32a9b45ceeaee051a04c8ed4320f5add3c51bfa20879b765b70/kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2", size = 80281, upload-time = "2025-08-10T21:27:45.369Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/dbd2ecdce306f1d07a1aaf324817ee993aab7aee9db47ceac757deabafbe/kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:464415881e4801295659462c49461a24fb107c140de781d55518c4b80cb6790f", size = 78009, upload-time = "2025-08-10T21:27:46.376Z" }, + { url = "https://files.pythonhosted.org/packages/da/e9/0d4add7873a73e462aeb45c036a2dead2562b825aa46ba326727b3f31016/kiwisolver-1.4.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fb940820c63a9590d31d88b815e7a3aa5915cad3ce735ab45f0c730b39547de1", size = 73929, upload-time = "2025-08-10T21:27:48.236Z" }, +] + +[[package]] +name = "langcodes" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "language-data" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3a/7a/5a97e327063409a5caa21541e6d08ae4a0f2da328447e9f2c7b39e179226/langcodes-3.5.0.tar.gz", hash = "sha256:1eef8168d07e51e131a2497ffecad4b663f6208e7c3ae3b8dc15c51734a6f801", size = 191030, upload-time = "2024-11-19T10:23:45.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/6b/068c2ea7a712bf805c62445bd9e9c06d7340358ef2824150eceac027444b/langcodes-3.5.0-py3-none-any.whl", hash = "sha256:853c69d1a35e0e13da2f427bb68fb2fa4a8f4fb899e0c62ad8df8d073dcfed33", size = 182974, upload-time = "2024-11-19T10:23:42.824Z" }, +] + +[[package]] +name = "language-data" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "marisa-trie" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/ce/3f144716a9f2cbf42aa86ebc8b085a184be25c80aa453eea17c294d239c1/language_data-1.3.0.tar.gz", hash = "sha256:7600ef8aa39555145d06c89f0c324bf7dab834ea0b0a439d8243762e3ebad7ec", size = 5129310, upload-time = "2024-11-19T10:21:37.912Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/e9/5a5ffd9b286db82be70d677d0a91e4d58f7912bb8dd026ddeeb4abe70679/language_data-1.3.0-py3-none-any.whl", hash = "sha256:e2ee943551b5ae5f89cd0e801d1fc3835bb0ef5b7e9c3a4e8e17b2b214548fbf", size = 5385760, upload-time = "2024-11-19T10:21:36.005Z" }, +] + +[[package]] +name = "locate" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/b0/6b303d4a2a20046dc396de914a6c1840253ff874630f00864ffe623acb68/locate-1.1.1.tar.gz", hash = "sha256:432750f5b7e89f8c99942ca7d8722ccd1e7954b20e6a973027fccb6cc00af857", size = 7831, upload-time = "2022-12-15T07:01:30.602Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/0d/9b6f11382b2f9080b5a366d20e90b4c08e547b6cd08c2a206729e6bad47a/locate-1.1.1-py3-none-any.whl", hash = "sha256:9e5e2f3516639240f4d975c08e95ae6a24ff4dd63d228f927541cdec30105755", size = 5364, upload-time = "2022-12-15T07:01:29.526Z" }, +] + +[[package]] +name = "marisa-trie" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/e3/c9066e74076b90f9701ccd23d6a0b8c1d583feefdec576dc3e1bb093c50d/marisa_trie-1.3.1.tar.gz", hash = "sha256:97107fd12f30e4f8fea97790343a2d2d9a79d93697fe14e1b6f6363c984ff85b", size = 212454, upload-time = "2025-08-26T15:13:18.401Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/eb/c18113555950ea25c421a5e8f7f280a9d7e9198a072f89d33ae9a5725ead/marisa_trie-1.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7e957aa4251a8e70b9fe02a16b2d190f18787902da563cb7ba865508b8e8fb04", size = 172432, upload-time = "2025-08-26T15:11:51.329Z" }, + { url = "https://files.pythonhosted.org/packages/b5/98/6d3f507a7340697d25d53839e68b516d3d01a3714edf33d484896250189b/marisa_trie-1.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e5888b269e790356ce4525f3e8df1fe866d1497b7d7fb7548cfec883cb985288", size = 156327, upload-time = "2025-08-26T15:11:52.646Z" }, + { url = "https://files.pythonhosted.org/packages/be/39/78d6def87a6effec6480ef1474d4cc81ef9845c78281ac5a6c07a6440744/marisa_trie-1.3.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f81344d212cb41992340b0b8a67e375f44da90590b884204fd3fa5e02107df2", size = 1219155, upload-time = "2025-08-26T15:11:53.915Z" }, + { url = "https://files.pythonhosted.org/packages/a6/b4/3b60c26cb9a2c623f47eeed84cfa6ebd3f71c5bd95ef32ed526e4ac689dc/marisa_trie-1.3.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3715d779561699471edde70975e07b1de7dddb2816735d40ed16be4b32054188", size = 1239413, upload-time = "2025-08-26T15:11:55.655Z" }, + { url = "https://files.pythonhosted.org/packages/21/ef/9c7fca5bf133bdb144317843881c8b0c74d2acb7fa209f793c29422e7669/marisa_trie-1.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:47631614c5243ed7d15ae0af8245fcc0599f5b7921fae2a4ae992afb27c9afbb", size = 2161737, upload-time = "2025-08-26T15:11:56.832Z" }, + { url = "https://files.pythonhosted.org/packages/1c/03/d5f630498bf4b8baf2d6484651255f601e9fdc6d42a83288e8b2420ebc9b/marisa_trie-1.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ad82ab8a58562cf69e6b786debcc7638b28df12f9f1c7bcffb07efb5c1f09cbd", size = 2250038, upload-time = "2025-08-26T15:11:58.165Z" }, + { url = "https://files.pythonhosted.org/packages/00/6b/c12f055dbb13d22b0f8e1f3da9cb734f581b516cc0e3c909e3f39368f676/marisa_trie-1.3.1-cp310-cp310-win32.whl", hash = "sha256:9f92d3577c72d5a97af5c8e3d98247b79c8ccfb64ebf611311dcf631b11e5604", size = 117232, upload-time = "2025-08-26T15:11:59.616Z" }, + { url = "https://files.pythonhosted.org/packages/f2/fd/988a19587c7bb8f03fb80e17335f75ca2d5538df4909727012b4bdff8f99/marisa_trie-1.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:a5a0a58ffe2a7eb3f870214c6df8f9a43ce768bd8fed883e6ba8c77645666b63", size = 143231, upload-time = "2025-08-26T15:12:00.52Z" }, + { url = "https://files.pythonhosted.org/packages/a7/bf/2f1fe6c9fcd2b509c6dfaaf26e35128947d6d3718d0b39510903c55b7bed/marisa_trie-1.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ef045f694ef66079b4e00c4c9063a00183d6af7d1ff643de6ea5c3b0d9af01b", size = 174027, upload-time = "2025-08-26T15:12:01.434Z" }, + { url = "https://files.pythonhosted.org/packages/a9/5a/de7936d58ed0de847180cee2b95143d420223c5ade0c093d55113f628237/marisa_trie-1.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cbd28f95d5f30d9a7af6130869568e75bfd7ef2e0adfb1480f1f44480f5d3603", size = 158478, upload-time = "2025-08-26T15:12:02.429Z" }, + { url = "https://files.pythonhosted.org/packages/48/cc/80611aadefcd0bcf8cd1795cb4643bb27213319a221ba04fe071da0b75cd/marisa_trie-1.3.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b173ec46d521308f7c97d96d6e05cf2088e0548f82544ec9a8656af65593304d", size = 1257535, upload-time = "2025-08-26T15:12:04.271Z" }, + { url = "https://files.pythonhosted.org/packages/36/89/c4eeefb956318047036e6bdc572b6112b2059d595e85961267a90aa40458/marisa_trie-1.3.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:954fef9185f8a79441b4e433695116636bf66402945cfee404f8983bafa59788", size = 1275566, upload-time = "2025-08-26T15:12:05.874Z" }, + { url = "https://files.pythonhosted.org/packages/c4/63/d775a2fdfc4b555120381cd2aa6dff1845576bc14fb13796ae1b1e8dbaf7/marisa_trie-1.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ca644534f15f85bba14c412afc17de07531e79a766ce85b8dbf3f8b6e7758f20", size = 2199831, upload-time = "2025-08-26T15:12:07.175Z" }, + { url = "https://files.pythonhosted.org/packages/50/aa/e5053927dc3cac77acc9b27f6f87e75c880f5d3d5eac9111fe13b1d8bf6f/marisa_trie-1.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3834304fdeaa1c9b73596ad5a6c01a44fc19c13c115194704b85f7fbdf0a7b8e", size = 2283830, upload-time = "2025-08-26T15:12:08.319Z" }, + { url = "https://files.pythonhosted.org/packages/71/3e/e314906d0de5b1a44780a23c79bb62a9aafd876e2a4e80fb34f58c721da4/marisa_trie-1.3.1-cp311-cp311-win32.whl", hash = "sha256:70b4c96f9119cfeb4dc6a0cf4afc9f92f0b002cde225bcd910915d976c78e66a", size = 117335, upload-time = "2025-08-26T15:12:09.776Z" }, + { url = "https://files.pythonhosted.org/packages/b0/2b/85623566621135de3d57497811f94679b4fb2a8f16148ef67133c2abab7a/marisa_trie-1.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:986eaf35a7f63c878280609ecd37edf8a074f7601c199acfec81d03f1ee9a39a", size = 143985, upload-time = "2025-08-26T15:12:10.988Z" }, + { url = "https://files.pythonhosted.org/packages/3f/40/ee7ea61b88d62d2189b5c4a27bc0fc8d9c32f8b8dc6daf1c93a7b7ad34ac/marisa_trie-1.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b7c1e7fa6c3b855e8cfbabf38454d7decbaba1c567d0cd58880d033c6b363bd", size = 173454, upload-time = "2025-08-26T15:12:12.13Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fc/58635811586898041004b2197a085253706ede211324a53ec01612a50e20/marisa_trie-1.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c12b44c190deb0d67655021da1f2d0a7d61a257bf844101cf982e68ed344f28d", size = 155305, upload-time = "2025-08-26T15:12:13.374Z" }, + { url = "https://files.pythonhosted.org/packages/fe/98/88ca0c98d37034a3237acaf461d210cbcfeb6687929e5ba0e354971fa3ed/marisa_trie-1.3.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9688c7b45f744366a4ef661e399f24636ebe440d315ab35d768676c59c613186", size = 1244834, upload-time = "2025-08-26T15:12:14.795Z" }, + { url = "https://files.pythonhosted.org/packages/f3/5f/93b3e3607ccd693a768eafee60829cd14ea1810b75aa48e8b20e27b332c4/marisa_trie-1.3.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99a00cab4cf9643a87977c87a5c8961aa44fff8d5dd46e00250135f686e7dedf", size = 1265148, upload-time = "2025-08-26T15:12:16.229Z" }, + { url = "https://files.pythonhosted.org/packages/db/6e/051d7d25c7fb2b3df605c8bd782513ebbb33fddf3bae6cf46cf268cca89f/marisa_trie-1.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:83efc045fc58ca04c91a96c9b894d8a19ac6553677a76f96df01ff9f0405f53d", size = 2172726, upload-time = "2025-08-26T15:12:18.467Z" }, + { url = "https://files.pythonhosted.org/packages/58/da/244d9d4e414ce6c73124cba4cc293dd140bf3b04ca18dec64c2775cca951/marisa_trie-1.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0b9816ab993001a7854b02a7daec228892f35bd5ab0ac493bacbd1b80baec9f1", size = 2256104, upload-time = "2025-08-26T15:12:20.168Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f1/1a36ecd7da6668685a7753522af89a19928ffc80f1cc1dbc301af216f011/marisa_trie-1.3.1-cp312-cp312-win32.whl", hash = "sha256:c785fd6dae9daa6825734b7b494cdac972f958be1f9cb3fb1f32be8598d2b936", size = 115624, upload-time = "2025-08-26T15:12:21.233Z" }, + { url = "https://files.pythonhosted.org/packages/35/b2/aabd1c9f1c102aa31d66633ed5328c447be166e0a703f9723e682478fd83/marisa_trie-1.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:9868b7a8e0f648d09ffe25ac29511e6e208cc5fb0d156c295385f9d5dc2a138e", size = 138562, upload-time = "2025-08-26T15:12:22.632Z" }, + { url = "https://files.pythonhosted.org/packages/46/a2/8331b995c1b3eee83aa745f4a6502d737ec523d5955a48f167d4177db105/marisa_trie-1.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9de573d933db4753a50af891bcb3ffbfe14e200406214c223aa5dfe2163f316d", size = 172272, upload-time = "2025-08-26T15:12:24.016Z" }, + { url = "https://files.pythonhosted.org/packages/97/b8/7b9681b5c0ea1bb950f907a4e3919eb7f7b7b3febafaae346f3b3f199f6f/marisa_trie-1.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4bae4f920f2a1082eaf766c1883df7da84abdf333bafa15b8717c10416a615e", size = 154671, upload-time = "2025-08-26T15:12:25.013Z" }, + { url = "https://files.pythonhosted.org/packages/ca/16/929c1f83fdcff13f8d08500f434aaa18c21c8168d16cf81585d69085e980/marisa_trie-1.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9f2b97fcfd5e2dbb0090d0664023872dcde990df0b545eca8d0ce95795a409", size = 1238754, upload-time = "2025-08-26T15:12:26.217Z" }, + { url = "https://files.pythonhosted.org/packages/0f/0a/b0e04d3ef91a87d4c7ea0b66c004fdfc6e65c9ed83edaebecfb482dfe0ed/marisa_trie-1.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecdb19d33b26738a32602ef432b06cc6deeca4b498ce67ba8e5e39c8a7c19745", size = 1262653, upload-time = "2025-08-26T15:12:27.422Z" }, + { url = "https://files.pythonhosted.org/packages/de/1f/0ecf610ddc9a209ee63116baabb47584d5b8ecd01610091a593d9429537e/marisa_trie-1.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7416f1a084eb889c5792c57317875aeaa86abfe0bdc6f167712cebcec1d36ee", size = 2172399, upload-time = "2025-08-26T15:12:28.926Z" }, + { url = "https://files.pythonhosted.org/packages/ac/74/6b47deff3b3920449c135b9187c80f0d656adcdc5d41463745a61b012ea1/marisa_trie-1.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee428575377e29c636f2b4b3b0488875dcea310c6c5b3412ec4ef997f7bb37cc", size = 2255138, upload-time = "2025-08-26T15:12:30.271Z" }, + { url = "https://files.pythonhosted.org/packages/bd/fa/3dbcbe93dfaa626a5b3e741e7bcf3d7389aa5777175213bd8d9a9d3c992d/marisa_trie-1.3.1-cp313-cp313-win32.whl", hash = "sha256:d0f87bdf660f01e88ab3a507955697b2e3284065afa0b94fc9e77d6ad153ed5e", size = 115391, upload-time = "2025-08-26T15:12:31.465Z" }, + { url = "https://files.pythonhosted.org/packages/3b/ce/ddfab303646b21aef07ff9dbc83fba92e5d493f49d3bc03d899ffd45c86f/marisa_trie-1.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:a83f5f7ae3494e0cc25211296252b1b86901c788ed82c83adda19d0c98f828d6", size = 139130, upload-time = "2025-08-26T15:12:32.4Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1e/734b618048ad05c50cb1673ce2c6e836dc38ddeeeb011ed1804af07327a4/marisa_trie-1.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a850b151bd1e3a5d9afef113adc22727d696603659d575d7e84f994bd8d04bf1", size = 175131, upload-time = "2025-08-26T15:12:33.728Z" }, + { url = "https://files.pythonhosted.org/packages/d3/78/c7051147cc918cb8ff4a2920e11a9b17d9dcb4d8fc122122694b486e2bfe/marisa_trie-1.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9dc61fb8f8993589544f6df268229c6cf0a56ad4ed3e8585a9cd23c5ad79527b", size = 163094, upload-time = "2025-08-26T15:12:35.312Z" }, + { url = "https://files.pythonhosted.org/packages/ee/b8/3b904178d7878319aacaabae5131c1f281519aaac0f8c68c8ed312912ccf/marisa_trie-1.3.1-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4bd41a6e73c0d0adafe4de449b6d35530a4ce6a836a6ee839baf117785ecfd7", size = 1279812, upload-time = "2025-08-26T15:12:36.831Z" }, + { url = "https://files.pythonhosted.org/packages/fb/bf/e77a1284247b980560b4104bbdd5d06ed2c2ae3d56ab954f97293b6dbbcd/marisa_trie-1.3.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8c8b2386d2d22c57880ed20a913ceca86363765623175671137484a7d223f07a", size = 1285690, upload-time = "2025-08-26T15:12:38.754Z" }, + { url = "https://files.pythonhosted.org/packages/48/82/f6f10db5ec72de2642499f3a6e4e8607bbd2cfb28269ea08d0d8ddac3313/marisa_trie-1.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c56001badaf1779afae5c24b7ab85938644ab8ef3c5fd438ab5d49621b84482", size = 2197943, upload-time = "2025-08-26T15:12:40.584Z" }, + { url = "https://files.pythonhosted.org/packages/2a/d0/74b6c3011b1ebf4a8131430156b14c3af694082cf34c392fff766096fd4b/marisa_trie-1.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83a3748088d117a9b15d8981c947df9e4f56eb2e4b5456ae34fe1f83666c9185", size = 2280132, upload-time = "2025-08-26T15:12:42.059Z" }, + { url = "https://files.pythonhosted.org/packages/28/b2/b8b0cb738fa3ab07309ed92025c6e1b278f84c7255e976921a52b30d8d1b/marisa_trie-1.3.1-cp313-cp313t-win32.whl", hash = "sha256:137010598d8cebc53dbfb7caf59bde96c33a6af555e3e1bdbf30269b6a157e1e", size = 126446, upload-time = "2025-08-26T15:12:43.339Z" }, + { url = "https://files.pythonhosted.org/packages/b6/c6/2381648d0c946556ef51c673397cea40712d945444ceed0a0a0b51a174d2/marisa_trie-1.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:ec633e108f277f2b7f4671d933a909f39bba549910bf103e2940b87a14da2783", size = 153885, upload-time = "2025-08-26T15:12:44.309Z" }, + { url = "https://files.pythonhosted.org/packages/40/8a/590f25a281e08879791aabec7b8584c7934ff3d5f9d52859197d587246ec/marisa_trie-1.3.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:389721481c14a92fa042e4b91ae065bff13e2bc567c85a10aa9d9de80aaa8622", size = 172803, upload-time = "2025-08-26T15:12:45.342Z" }, + { url = "https://files.pythonhosted.org/packages/20/7f/fd19a4aa57ad169d08e518a6ee2438e7e77bfba7786c59f65891db69d202/marisa_trie-1.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e6f3b45def6ff23e254eeaa9079267004f0069d0a34eba30a620780caa4f2cb", size = 155506, upload-time = "2025-08-26T15:12:46.701Z" }, + { url = "https://files.pythonhosted.org/packages/e3/05/857832b8fe6b2ec441de1154eadc66dee067ce5fb6673c3ee0b8616108ee/marisa_trie-1.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a96ef3e461ecc85ec7d2233ddc449ff5a3fbdc520caea752bc5bc8faa975231", size = 1239979, upload-time = "2025-08-26T15:12:47.943Z" }, + { url = "https://files.pythonhosted.org/packages/4c/08/f9ea8b720a627d54e8e19f19a0ec1cc2011e01aa2b4f40d078e7f5e9e21f/marisa_trie-1.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5370f9ef6c008e502537cc1ff518c80ddf749367ce90179efa0e7f6275903a76", size = 1255705, upload-time = "2025-08-26T15:12:49.24Z" }, + { url = "https://files.pythonhosted.org/packages/e9/c3/42360fb38cdfde5db1783e2d7cfeb8b91eea837f89ef678f308ee026d794/marisa_trie-1.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0dcd42774e367ceb423c211a4fc8e7ce586acfaf0929c9c06d98002112075239", size = 2175092, upload-time = "2025-08-26T15:12:50.602Z" }, + { url = "https://files.pythonhosted.org/packages/09/ba/215b0d821fd37cdc600e834a75708aa2e117124dcf495c9a6c6dc7fdcb6b/marisa_trie-1.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3e2a0e1be95237981bd375a388f44b33d69ea5669a2f79fea038e45fff326595", size = 2250454, upload-time = "2025-08-26T15:12:52.435Z" }, + { url = "https://files.pythonhosted.org/packages/f5/a3/292ab31a12ec1cb356e6bc8b9cc8aaec920aa892a805757c011d77e8cd93/marisa_trie-1.3.1-cp314-cp314-win32.whl", hash = "sha256:c7a33506d0451112911c69f38d55da3e0e050f2be0ea4e5176865cf03baf26a9", size = 119101, upload-time = "2025-08-26T15:12:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/95/83/0ea5de53209993cf301dd9d18d4cb22c20c84c753b4357b66660a8b9eb48/marisa_trie-1.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:68678816818efcd4a1787b557af81f215b989ec88680a86c85c34c914d413690", size = 142886, upload-time = "2025-08-26T15:12:54.835Z" }, + { url = "https://files.pythonhosted.org/packages/37/00/c7e063867988067992a9d9d2aceaede0be7787ca6d77ef34f2eca9d2708e/marisa_trie-1.3.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9e467e13971c64db6aed8afe4c2a131c3f73f048bec3f788a6141216acda598d", size = 175163, upload-time = "2025-08-26T15:12:55.908Z" }, + { url = "https://files.pythonhosted.org/packages/5f/64/eaf49d10c8506ecd717bbbeda907e474842c298354a444b875741ef4a0d9/marisa_trie-1.3.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:076731f79f8603cb3216cb6e5bbbc56536c89f63f175ad47014219ecb01e5996", size = 163119, upload-time = "2025-08-26T15:12:58.054Z" }, + { url = "https://files.pythonhosted.org/packages/b4/26/f24dd9c98ce6fc8c8d554b556e1c43f326c5df414b79aba33bd7d2d2fbfd/marisa_trie-1.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82de2de90488d0fbbf74cf9f20e1afd62e320693b88f5e9565fc80b28f5bbad3", size = 1277783, upload-time = "2025-08-26T15:12:59.225Z" }, + { url = "https://files.pythonhosted.org/packages/b2/1a/efd63e75d1374e08f8ebe2e15ff1b1ed5f6d5cf57614a5b0884bd9c882ee/marisa_trie-1.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c2bc6bee737f4d47fce48c5b03a7bd3214ef2d83eb5c9f84210091370a5f195", size = 1282309, upload-time = "2025-08-26T15:13:00.797Z" }, + { url = "https://files.pythonhosted.org/packages/33/4c/0cefa1eceec7858766af5939979857ac079c6c5251e00c6991c1a26bb1b7/marisa_trie-1.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:56043cf908ddf3d7364498085dbc2855d4ea8969aff3bf2439a79482a79e68e2", size = 2196594, upload-time = "2025-08-26T15:13:02.158Z" }, + { url = "https://files.pythonhosted.org/packages/bb/64/900f4132fc345be4b40073e66284707afa4cc203d8d0f1fe78c6b111cd47/marisa_trie-1.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9651daa1fdc471df5a5fa6a4833d3b01e76ac512eea141a5995681aebac5555f", size = 2277730, upload-time = "2025-08-26T15:13:03.528Z" }, + { url = "https://files.pythonhosted.org/packages/62/ab/6d6cf25a5c8835589a601a9a916ec5cdee740e277fed8ee620df546834bb/marisa_trie-1.3.1-cp314-cp314t-win32.whl", hash = "sha256:c6571462417cda2239b1ade86ceaf3852da9b52c6286046e87d404afc6da20a7", size = 131409, upload-time = "2025-08-26T15:13:05.106Z" }, + { url = "https://files.pythonhosted.org/packages/9a/61/c4efc044141429e67e8fd5536be86d76303f250179c7f92b2cc0c72e8d0b/marisa_trie-1.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:9e6496bbad3068e3bbbb934b1e1307bf1a9cb4609f9ec47b57e8ea37f1b5ee40", size = 162564, upload-time = "2025-08-26T15:13:06.112Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" }, + { url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" }, + { url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" }, + { url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" }, + { url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" }, + { url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" }, + { url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" }, + { url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" }, + { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, + { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, + { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "matplotlib" +version = "3.10.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy", version = "1.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "contourpy", version = "1.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "cycler" }, + { name = "fonttools" }, + { name = "kiwisolver" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "pyparsing" }, + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/e2/d2d5295be2f44c678ebaf3544ba32d20c1f9ef08c49fe47f496180e1db15/matplotlib-3.10.7.tar.gz", hash = "sha256:a06ba7e2a2ef9131c79c49e63dad355d2d878413a0376c1727c8b9335ff731c7", size = 34804865, upload-time = "2025-10-09T00:28:00.669Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/87/3932d5778ab4c025db22710b61f49ccaed3956c5cf46ffb2ffa7492b06d9/matplotlib-3.10.7-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7ac81eee3b7c266dd92cee1cd658407b16c57eed08c7421fa354ed68234de380", size = 8247141, upload-time = "2025-10-09T00:26:06.023Z" }, + { url = "https://files.pythonhosted.org/packages/45/a8/bfed45339160102bce21a44e38a358a1134a5f84c26166de03fb4a53208f/matplotlib-3.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:667ecd5d8d37813a845053d8f5bf110b534c3c9f30e69ebd25d4701385935a6d", size = 8107995, upload-time = "2025-10-09T00:26:08.669Z" }, + { url = "https://files.pythonhosted.org/packages/e2/3c/5692a2d9a5ba848fda3f48d2b607037df96460b941a59ef236404b39776b/matplotlib-3.10.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc1c51b846aca49a5a8b44fbba6a92d583a35c64590ad9e1e950dc88940a4297", size = 8680503, upload-time = "2025-10-09T00:26:10.607Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a0/86ace53c48b05d0e6e9c127b2ace097434901f3e7b93f050791c8243201a/matplotlib-3.10.7-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a11c2e9e72e7de09b7b72e62f3df23317c888299c875e2b778abf1eda8c0a42", size = 9514982, upload-time = "2025-10-09T00:26:12.594Z" }, + { url = "https://files.pythonhosted.org/packages/a6/81/ead71e2824da8f72640a64166d10e62300df4ae4db01a0bac56c5b39fa51/matplotlib-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f19410b486fdd139885ace124e57f938c1e6a3210ea13dd29cab58f5d4bc12c7", size = 9566429, upload-time = "2025-10-09T00:26:14.758Z" }, + { url = "https://files.pythonhosted.org/packages/65/7d/954b3067120456f472cce8fdcacaf4a5fcd522478db0c37bb243c7cb59dd/matplotlib-3.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:b498e9e4022f93de2d5a37615200ca01297ceebbb56fe4c833f46862a490f9e3", size = 8108174, upload-time = "2025-10-09T00:26:17.015Z" }, + { url = "https://files.pythonhosted.org/packages/fc/bc/0fb489005669127ec13f51be0c6adc074d7cf191075dab1da9fe3b7a3cfc/matplotlib-3.10.7-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:53b492410a6cd66c7a471de6c924f6ede976e963c0f3097a3b7abfadddc67d0a", size = 8257507, upload-time = "2025-10-09T00:26:19.073Z" }, + { url = "https://files.pythonhosted.org/packages/e2/6a/d42588ad895279ff6708924645b5d2ed54a7fb2dc045c8a804e955aeace1/matplotlib-3.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d9749313deb729f08207718d29c86246beb2ea3fdba753595b55901dee5d2fd6", size = 8119565, upload-time = "2025-10-09T00:26:21.023Z" }, + { url = "https://files.pythonhosted.org/packages/10/b7/4aa196155b4d846bd749cf82aa5a4c300cf55a8b5e0dfa5b722a63c0f8a0/matplotlib-3.10.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2222c7ba2cbde7fe63032769f6eb7e83ab3227f47d997a8453377709b7fe3a5a", size = 8692668, upload-time = "2025-10-09T00:26:22.967Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e7/664d2b97016f46683a02d854d730cfcf54ff92c1dafa424beebef50f831d/matplotlib-3.10.7-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e91f61a064c92c307c5a9dc8c05dc9f8a68f0a3be199d9a002a0622e13f874a1", size = 9521051, upload-time = "2025-10-09T00:26:25.041Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a3/37aef1404efa615f49b5758a5e0261c16dd88f389bc1861e722620e4a754/matplotlib-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f1851eab59ca082c95df5a500106bad73672645625e04538b3ad0f69471ffcc", size = 9576878, upload-time = "2025-10-09T00:26:27.478Z" }, + { url = "https://files.pythonhosted.org/packages/33/cd/b145f9797126f3f809d177ca378de57c45413c5099c5990de2658760594a/matplotlib-3.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:6516ce375109c60ceec579e699524e9d504cd7578506f01150f7a6bc174a775e", size = 8115142, upload-time = "2025-10-09T00:26:29.774Z" }, + { url = "https://files.pythonhosted.org/packages/2e/39/63bca9d2b78455ed497fcf51a9c71df200a11048f48249038f06447fa947/matplotlib-3.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:b172db79759f5f9bc13ef1c3ef8b9ee7b37b0247f987fbbbdaa15e4f87fd46a9", size = 7992439, upload-time = "2025-10-09T00:26:40.32Z" }, + { url = "https://files.pythonhosted.org/packages/be/b3/09eb0f7796932826ec20c25b517d568627754f6c6462fca19e12c02f2e12/matplotlib-3.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7a0edb7209e21840e8361e91ea84ea676658aa93edd5f8762793dec77a4a6748", size = 8272389, upload-time = "2025-10-09T00:26:42.474Z" }, + { url = "https://files.pythonhosted.org/packages/11/0b/1ae80ddafb8652fd8046cb5c8460ecc8d4afccb89e2c6d6bec61e04e1eaf/matplotlib-3.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c380371d3c23e0eadf8ebff114445b9f970aff2010198d498d4ab4c3b41eea4f", size = 8128247, upload-time = "2025-10-09T00:26:44.77Z" }, + { url = "https://files.pythonhosted.org/packages/7d/18/95ae2e242d4a5c98bd6e90e36e128d71cf1c7e39b0874feaed3ef782e789/matplotlib-3.10.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d5f256d49fea31f40f166a5e3131235a5d2f4b7f44520b1cf0baf1ce568ccff0", size = 8696996, upload-time = "2025-10-09T00:26:46.792Z" }, + { url = "https://files.pythonhosted.org/packages/7e/3d/5b559efc800bd05cb2033aa85f7e13af51958136a48327f7c261801ff90a/matplotlib-3.10.7-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11ae579ac83cdf3fb72573bb89f70e0534de05266728740d478f0f818983c695", size = 9530153, upload-time = "2025-10-09T00:26:49.07Z" }, + { url = "https://files.pythonhosted.org/packages/88/57/eab4a719fd110312d3c220595d63a3c85ec2a39723f0f4e7fa7e6e3f74ba/matplotlib-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4c14b6acd16cddc3569a2d515cfdd81c7a68ac5639b76548cfc1a9e48b20eb65", size = 9593093, upload-time = "2025-10-09T00:26:51.067Z" }, + { url = "https://files.pythonhosted.org/packages/31/3c/80816f027b3a4a28cd2a0a6ef7f89a2db22310e945cd886ec25bfb399221/matplotlib-3.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:0d8c32b7ea6fb80b1aeff5a2ceb3fb9778e2759e899d9beff75584714afcc5ee", size = 8122771, upload-time = "2025-10-09T00:26:53.296Z" }, + { url = "https://files.pythonhosted.org/packages/de/77/ef1fc78bfe99999b2675435cc52120887191c566b25017d78beaabef7f2d/matplotlib-3.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:5f3f6d315dcc176ba7ca6e74c7768fb7e4cf566c49cb143f6bc257b62e634ed8", size = 7992812, upload-time = "2025-10-09T00:26:54.882Z" }, + { url = "https://files.pythonhosted.org/packages/02/9c/207547916a02c78f6bdd83448d9b21afbc42f6379ed887ecf610984f3b4e/matplotlib-3.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1d9d3713a237970569156cfb4de7533b7c4eacdd61789726f444f96a0d28f57f", size = 8273212, upload-time = "2025-10-09T00:26:56.752Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d0/b3d3338d467d3fc937f0bb7f256711395cae6f78e22cef0656159950adf0/matplotlib-3.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:37a1fea41153dd6ee061d21ab69c9cf2cf543160b1b85d89cd3d2e2a7902ca4c", size = 8128713, upload-time = "2025-10-09T00:26:59.001Z" }, + { url = "https://files.pythonhosted.org/packages/22/ff/6425bf5c20d79aa5b959d1ce9e65f599632345391381c9a104133fe0b171/matplotlib-3.10.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b3c4ea4948d93c9c29dc01c0c23eef66f2101bf75158c291b88de6525c55c3d1", size = 8698527, upload-time = "2025-10-09T00:27:00.69Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7f/ccdca06f4c2e6c7989270ed7829b8679466682f4cfc0f8c9986241c023b6/matplotlib-3.10.7-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22df30ffaa89f6643206cf13877191c63a50e8f800b038bc39bee9d2d4957632", size = 9529690, upload-time = "2025-10-09T00:27:02.664Z" }, + { url = "https://files.pythonhosted.org/packages/b8/95/b80fc2c1f269f21ff3d193ca697358e24408c33ce2b106a7438a45407b63/matplotlib-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b69676845a0a66f9da30e87f48be36734d6748024b525ec4710be40194282c84", size = 9593732, upload-time = "2025-10-09T00:27:04.653Z" }, + { url = "https://files.pythonhosted.org/packages/e1/b6/23064a96308b9aeceeffa65e96bcde459a2ea4934d311dee20afde7407a0/matplotlib-3.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:744991e0cc863dd669c8dc9136ca4e6e0082be2070b9d793cbd64bec872a6815", size = 8122727, upload-time = "2025-10-09T00:27:06.814Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a6/2faaf48133b82cf3607759027f82b5c702aa99cdfcefb7f93d6ccf26a424/matplotlib-3.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:fba2974df0bf8ce3c995fa84b79cde38326e0f7b5409e7a3a481c1141340bcf7", size = 7992958, upload-time = "2025-10-09T00:27:08.567Z" }, + { url = "https://files.pythonhosted.org/packages/4a/f0/b018fed0b599bd48d84c08794cb242227fe3341952da102ee9d9682db574/matplotlib-3.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:932c55d1fa7af4423422cb6a492a31cbcbdbe68fd1a9a3f545aa5e7a143b5355", size = 8316849, upload-time = "2025-10-09T00:27:10.254Z" }, + { url = "https://files.pythonhosted.org/packages/b0/b7/bb4f23856197659f275e11a2a164e36e65e9b48ea3e93c4ec25b4f163198/matplotlib-3.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e38c2d581d62ee729a6e144c47a71b3f42fb4187508dbbf4fe71d5612c3433b", size = 8178225, upload-time = "2025-10-09T00:27:12.241Z" }, + { url = "https://files.pythonhosted.org/packages/62/56/0600609893ff277e6f3ab3c0cef4eafa6e61006c058e84286c467223d4d5/matplotlib-3.10.7-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:786656bb13c237bbcebcd402f65f44dd61ead60ee3deb045af429d889c8dbc67", size = 8711708, upload-time = "2025-10-09T00:27:13.879Z" }, + { url = "https://files.pythonhosted.org/packages/d8/1a/6bfecb0cafe94d6658f2f1af22c43b76cf7a1c2f0dc34ef84cbb6809617e/matplotlib-3.10.7-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09d7945a70ea43bf9248f4b6582734c2fe726723204a76eca233f24cffc7ef67", size = 9541409, upload-time = "2025-10-09T00:27:15.684Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/95122a407d7f2e446fd865e2388a232a23f2b81934960ea802f3171518e4/matplotlib-3.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d0b181e9fa8daf1d9f2d4c547527b167cb8838fc587deabca7b5c01f97199e84", size = 9594054, upload-time = "2025-10-09T00:27:17.547Z" }, + { url = "https://files.pythonhosted.org/packages/13/76/75b194a43b81583478a81e78a07da8d9ca6ddf50dd0a2ccabf258059481d/matplotlib-3.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:31963603041634ce1a96053047b40961f7a29eb8f9a62e80cc2c0427aa1d22a2", size = 8200100, upload-time = "2025-10-09T00:27:20.039Z" }, + { url = "https://files.pythonhosted.org/packages/f5/9e/6aefebdc9f8235c12bdeeda44cc0383d89c1e41da2c400caf3ee2073a3ce/matplotlib-3.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:aebed7b50aa6ac698c90f60f854b47e48cd2252b30510e7a1feddaf5a3f72cbf", size = 8042131, upload-time = "2025-10-09T00:27:21.608Z" }, + { url = "https://files.pythonhosted.org/packages/0d/4b/e5bc2c321b6a7e3a75638d937d19ea267c34bd5a90e12bee76c4d7c7a0d9/matplotlib-3.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d883460c43e8c6b173fef244a2341f7f7c0e9725c7fe68306e8e44ed9c8fb100", size = 8273787, upload-time = "2025-10-09T00:27:23.27Z" }, + { url = "https://files.pythonhosted.org/packages/86/ad/6efae459c56c2fbc404da154e13e3a6039129f3c942b0152624f1c621f05/matplotlib-3.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07124afcf7a6504eafcb8ce94091c5898bbdd351519a1beb5c45f7a38c67e77f", size = 8131348, upload-time = "2025-10-09T00:27:24.926Z" }, + { url = "https://files.pythonhosted.org/packages/a6/5a/a4284d2958dee4116359cc05d7e19c057e64ece1b4ac986ab0f2f4d52d5a/matplotlib-3.10.7-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c17398b709a6cce3d9fdb1595c33e356d91c098cd9486cb2cc21ea2ea418e715", size = 9533949, upload-time = "2025-10-09T00:27:26.704Z" }, + { url = "https://files.pythonhosted.org/packages/de/ff/f3781b5057fa3786623ad8976fc9f7b0d02b2f28534751fd5a44240de4cf/matplotlib-3.10.7-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7146d64f561498764561e9cd0ed64fcf582e570fc519e6f521e2d0cfd43365e1", size = 9804247, upload-time = "2025-10-09T00:27:28.514Z" }, + { url = "https://files.pythonhosted.org/packages/47/5a/993a59facb8444efb0e197bf55f545ee449902dcee86a4dfc580c3b61314/matplotlib-3.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:90ad854c0a435da3104c01e2c6f0028d7e719b690998a2333d7218db80950722", size = 9595497, upload-time = "2025-10-09T00:27:30.418Z" }, + { url = "https://files.pythonhosted.org/packages/0d/a5/77c95aaa9bb32c345cbb49626ad8eb15550cba2e6d4c88081a6c2ac7b08d/matplotlib-3.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:4645fc5d9d20ffa3a39361fcdbcec731382763b623b72627806bf251b6388866", size = 8252732, upload-time = "2025-10-09T00:27:32.332Z" }, + { url = "https://files.pythonhosted.org/packages/74/04/45d269b4268d222390d7817dae77b159651909669a34ee9fdee336db5883/matplotlib-3.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:9257be2f2a03415f9105c486d304a321168e61ad450f6153d77c69504ad764bb", size = 8124240, upload-time = "2025-10-09T00:27:33.94Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c7/ca01c607bb827158b439208c153d6f14ddb9fb640768f06f7ca3488ae67b/matplotlib-3.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1e4bbad66c177a8fdfa53972e5ef8be72a5f27e6a607cec0d8579abd0f3102b1", size = 8316938, upload-time = "2025-10-09T00:27:35.534Z" }, + { url = "https://files.pythonhosted.org/packages/84/d2/5539e66e9f56d2fdec94bb8436f5e449683b4e199bcc897c44fbe3c99e28/matplotlib-3.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d8eb7194b084b12feb19142262165832fc6ee879b945491d1c3d4660748020c4", size = 8178245, upload-time = "2025-10-09T00:27:37.334Z" }, + { url = "https://files.pythonhosted.org/packages/77/b5/e6ca22901fd3e4fe433a82e583436dd872f6c966fca7e63cf806b40356f8/matplotlib-3.10.7-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4d41379b05528091f00e1728004f9a8d7191260f3862178b88e8fd770206318", size = 9541411, upload-time = "2025-10-09T00:27:39.387Z" }, + { url = "https://files.pythonhosted.org/packages/9e/99/a4524db57cad8fee54b7237239a8f8360bfcfa3170d37c9e71c090c0f409/matplotlib-3.10.7-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a74f79fafb2e177f240579bc83f0b60f82cc47d2f1d260f422a0627207008ca", size = 9803664, upload-time = "2025-10-09T00:27:41.492Z" }, + { url = "https://files.pythonhosted.org/packages/e6/a5/85e2edf76ea0ad4288d174926d9454ea85f3ce5390cc4e6fab196cbf250b/matplotlib-3.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:702590829c30aada1e8cef0568ddbffa77ca747b4d6e36c6d173f66e301f89cc", size = 9594066, upload-time = "2025-10-09T00:27:43.694Z" }, + { url = "https://files.pythonhosted.org/packages/39/69/9684368a314f6d83fe5c5ad2a4121a3a8e03723d2e5c8ea17b66c1bad0e7/matplotlib-3.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:f79d5de970fc90cd5591f60053aecfce1fcd736e0303d9f0bf86be649fa68fb8", size = 8342832, upload-time = "2025-10-09T00:27:45.543Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/e22e08da14bc1a0894184640d47819d2338b792732e20d292bf86e5ab785/matplotlib-3.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:cb783436e47fcf82064baca52ce748af71725d0352e1d31564cbe9c95df92b9c", size = 8172585, upload-time = "2025-10-09T00:27:47.185Z" }, + { url = "https://files.pythonhosted.org/packages/1e/6c/a9bcf03e9afb2a873e0a5855f79bce476d1023f26f8212969f2b7504756c/matplotlib-3.10.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5c09cf8f2793f81368f49f118b6f9f937456362bee282eac575cca7f84cda537", size = 8241204, upload-time = "2025-10-09T00:27:48.806Z" }, + { url = "https://files.pythonhosted.org/packages/5b/fd/0e6f5aa762ed689d9fa8750b08f1932628ffa7ed30e76423c399d19407d2/matplotlib-3.10.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:de66744b2bb88d5cd27e80dfc2ec9f0517d0a46d204ff98fe9e5f2864eb67657", size = 8104607, upload-time = "2025-10-09T00:27:50.876Z" }, + { url = "https://files.pythonhosted.org/packages/b9/a9/21c9439d698fac5f0de8fc68b2405b738ed1f00e1279c76f2d9aa5521ead/matplotlib-3.10.7-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:53cc80662dd197ece414dd5b66e07370201515a3eaf52e7c518c68c16814773b", size = 8682257, upload-time = "2025-10-09T00:27:52.597Z" }, + { url = "https://files.pythonhosted.org/packages/58/8f/76d5dc21ac64a49e5498d7f0472c0781dae442dd266a67458baec38288ec/matplotlib-3.10.7-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:15112bcbaef211bd663fa935ec33313b948e214454d949b723998a43357b17b0", size = 8252283, upload-time = "2025-10-09T00:27:54.739Z" }, + { url = "https://files.pythonhosted.org/packages/27/0d/9c5d4c2317feb31d819e38c9f947c942f42ebd4eb935fc6fd3518a11eaa7/matplotlib-3.10.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d2a959c640cdeecdd2ec3136e8ea0441da59bcaf58d67e9c590740addba2cb68", size = 8116733, upload-time = "2025-10-09T00:27:56.406Z" }, + { url = "https://files.pythonhosted.org/packages/9a/cc/3fe688ff1355010937713164caacf9ed443675ac48a997bab6ed23b3f7c0/matplotlib-3.10.7-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3886e47f64611046bc1db523a09dd0a0a6bed6081e6f90e13806dd1d1d1b5e91", size = 8693919, upload-time = "2025-10-09T00:27:58.41Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "mpmath" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" }, +] + +[[package]] +name = "msgpack" +version = "1.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/f2/bfb55a6236ed8725a96b0aa3acbd0ec17588e6a2c3b62a93eb513ed8783f/msgpack-1.1.2.tar.gz", hash = "sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e", size = 173581, upload-time = "2025-10-08T09:15:56.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f5/a2/3b68a9e769db68668b25c6108444a35f9bd163bb848c0650d516761a59c0/msgpack-1.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0051fffef5a37ca2cd16978ae4f0aef92f164df86823871b5162812bebecd8e2", size = 81318, upload-time = "2025-10-08T09:14:38.722Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e1/2b720cc341325c00be44e1ed59e7cfeae2678329fbf5aa68f5bda57fe728/msgpack-1.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a605409040f2da88676e9c9e5853b3449ba8011973616189ea5ee55ddbc5bc87", size = 83786, upload-time = "2025-10-08T09:14:40.082Z" }, + { url = "https://files.pythonhosted.org/packages/71/e5/c2241de64bfceac456b140737812a2ab310b10538a7b34a1d393b748e095/msgpack-1.1.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b696e83c9f1532b4af884045ba7f3aa741a63b2bc22617293a2c6a7c645f251", size = 398240, upload-time = "2025-10-08T09:14:41.151Z" }, + { url = "https://files.pythonhosted.org/packages/b7/09/2a06956383c0fdebaef5aa9246e2356776f12ea6f2a44bd1368abf0e46c4/msgpack-1.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:365c0bbe981a27d8932da71af63ef86acc59ed5c01ad929e09a0b88c6294e28a", size = 406070, upload-time = "2025-10-08T09:14:42.821Z" }, + { url = "https://files.pythonhosted.org/packages/0e/74/2957703f0e1ef20637d6aead4fbb314330c26f39aa046b348c7edcf6ca6b/msgpack-1.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:41d1a5d875680166d3ac5c38573896453bbbea7092936d2e107214daf43b1d4f", size = 393403, upload-time = "2025-10-08T09:14:44.38Z" }, + { url = "https://files.pythonhosted.org/packages/a5/09/3bfc12aa90f77b37322fc33e7a8a7c29ba7c8edeadfa27664451801b9860/msgpack-1.1.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354e81bcdebaab427c3df4281187edc765d5d76bfb3a7c125af9da7a27e8458f", size = 398947, upload-time = "2025-10-08T09:14:45.56Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4f/05fcebd3b4977cb3d840f7ef6b77c51f8582086de5e642f3fefee35c86fc/msgpack-1.1.2-cp310-cp310-win32.whl", hash = "sha256:e64c8d2f5e5d5fda7b842f55dec6133260ea8f53c4257d64494c534f306bf7a9", size = 64769, upload-time = "2025-10-08T09:14:47.334Z" }, + { url = "https://files.pythonhosted.org/packages/d0/3e/b4547e3a34210956382eed1c85935fff7e0f9b98be3106b3745d7dec9c5e/msgpack-1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:db6192777d943bdaaafb6ba66d44bf65aa0e9c5616fa1d2da9bb08828c6b39aa", size = 71293, upload-time = "2025-10-08T09:14:48.665Z" }, + { url = "https://files.pythonhosted.org/packages/2c/97/560d11202bcd537abca693fd85d81cebe2107ba17301de42b01ac1677b69/msgpack-1.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e86a607e558d22985d856948c12a3fa7b42efad264dca8a3ebbcfa2735d786c", size = 82271, upload-time = "2025-10-08T09:14:49.967Z" }, + { url = "https://files.pythonhosted.org/packages/83/04/28a41024ccbd67467380b6fb440ae916c1e4f25e2cd4c63abe6835ac566e/msgpack-1.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:283ae72fc89da59aa004ba147e8fc2f766647b1251500182fac0350d8af299c0", size = 84914, upload-time = "2025-10-08T09:14:50.958Z" }, + { url = "https://files.pythonhosted.org/packages/71/46/b817349db6886d79e57a966346cf0902a426375aadc1e8e7a86a75e22f19/msgpack-1.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61c8aa3bd513d87c72ed0b37b53dd5c5a0f58f2ff9f26e1555d3bd7948fb7296", size = 416962, upload-time = "2025-10-08T09:14:51.997Z" }, + { url = "https://files.pythonhosted.org/packages/da/e0/6cc2e852837cd6086fe7d8406af4294e66827a60a4cf60b86575a4a65ca8/msgpack-1.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:454e29e186285d2ebe65be34629fa0e8605202c60fbc7c4c650ccd41870896ef", size = 426183, upload-time = "2025-10-08T09:14:53.477Z" }, + { url = "https://files.pythonhosted.org/packages/25/98/6a19f030b3d2ea906696cedd1eb251708e50a5891d0978b012cb6107234c/msgpack-1.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7bc8813f88417599564fafa59fd6f95be417179f76b40325b500b3c98409757c", size = 411454, upload-time = "2025-10-08T09:14:54.648Z" }, + { url = "https://files.pythonhosted.org/packages/b7/cd/9098fcb6adb32187a70b7ecaabf6339da50553351558f37600e53a4a2a23/msgpack-1.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bafca952dc13907bdfdedfc6a5f579bf4f292bdd506fadb38389afa3ac5b208e", size = 422341, upload-time = "2025-10-08T09:14:56.328Z" }, + { url = "https://files.pythonhosted.org/packages/e6/ae/270cecbcf36c1dc85ec086b33a51a4d7d08fc4f404bdbc15b582255d05ff/msgpack-1.1.2-cp311-cp311-win32.whl", hash = "sha256:602b6740e95ffc55bfb078172d279de3773d7b7db1f703b2f1323566b878b90e", size = 64747, upload-time = "2025-10-08T09:14:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/2a/79/309d0e637f6f37e83c711f547308b91af02b72d2326ddd860b966080ef29/msgpack-1.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:d198d275222dc54244bf3327eb8cbe00307d220241d9cec4d306d49a44e85f68", size = 71633, upload-time = "2025-10-08T09:14:59.177Z" }, + { url = "https://files.pythonhosted.org/packages/73/4d/7c4e2b3d9b1106cd0aa6cb56cc57c6267f59fa8bfab7d91df5adc802c847/msgpack-1.1.2-cp311-cp311-win_arm64.whl", hash = "sha256:86f8136dfa5c116365a8a651a7d7484b65b13339731dd6faebb9a0242151c406", size = 64755, upload-time = "2025-10-08T09:15:00.48Z" }, + { url = "https://files.pythonhosted.org/packages/ad/bd/8b0d01c756203fbab65d265859749860682ccd2a59594609aeec3a144efa/msgpack-1.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:70a0dff9d1f8da25179ffcf880e10cf1aad55fdb63cd59c9a49a1b82290062aa", size = 81939, upload-time = "2025-10-08T09:15:01.472Z" }, + { url = "https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb", size = 85064, upload-time = "2025-10-08T09:15:03.764Z" }, + { url = "https://files.pythonhosted.org/packages/f2/60/a064b0345fc36c4c3d2c743c82d9100c40388d77f0b48b2f04d6041dbec1/msgpack-1.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c63eea553c69ab05b6747901b97d620bb2a690633c77f23feb0c6a947a8a7b8f", size = 417131, upload-time = "2025-10-08T09:15:05.136Z" }, + { url = "https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42", size = 427556, upload-time = "2025-10-08T09:15:06.837Z" }, + { url = "https://files.pythonhosted.org/packages/f5/87/ffe21d1bf7d9991354ad93949286f643b2bb6ddbeab66373922b44c3b8cc/msgpack-1.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2929af52106ca73fcb28576218476ffbb531a036c2adbcf54a3664de124303e9", size = 404920, upload-time = "2025-10-08T09:15:08.179Z" }, + { url = "https://files.pythonhosted.org/packages/ff/41/8543ed2b8604f7c0d89ce066f42007faac1eaa7d79a81555f206a5cdb889/msgpack-1.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be52a8fc79e45b0364210eef5234a7cf8d330836d0a64dfbb878efa903d84620", size = 415013, upload-time = "2025-10-08T09:15:09.83Z" }, + { url = "https://files.pythonhosted.org/packages/41/0d/2ddfaa8b7e1cee6c490d46cb0a39742b19e2481600a7a0e96537e9c22f43/msgpack-1.1.2-cp312-cp312-win32.whl", hash = "sha256:1fff3d825d7859ac888b0fbda39a42d59193543920eda9d9bea44d958a878029", size = 65096, upload-time = "2025-10-08T09:15:11.11Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b", size = 72708, upload-time = "2025-10-08T09:15:12.554Z" }, + { url = "https://files.pythonhosted.org/packages/c5/31/5b1a1f70eb0e87d1678e9624908f86317787b536060641d6798e3cf70ace/msgpack-1.1.2-cp312-cp312-win_arm64.whl", hash = "sha256:be5980f3ee0e6bd44f3a9e9dea01054f175b50c3e6cdb692bc9424c0bbb8bf69", size = 64119, upload-time = "2025-10-08T09:15:13.589Z" }, + { url = "https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4efd7b5979ccb539c221a4c4e16aac1a533efc97f3b759bb5a5ac9f6d10383bf", size = 81212, upload-time = "2025-10-08T09:15:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42eefe2c3e2af97ed470eec850facbe1b5ad1d6eacdbadc42ec98e7dcf68b4b7", size = 84315, upload-time = "2025-10-08T09:15:15.543Z" }, + { url = "https://files.pythonhosted.org/packages/d3/68/93180dce57f684a61a88a45ed13047558ded2be46f03acb8dec6d7c513af/msgpack-1.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1fdf7d83102bf09e7ce3357de96c59b627395352a4024f6e2458501f158bf999", size = 412721, upload-time = "2025-10-08T09:15:16.567Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fac4be746328f90caa3cd4bc67e6fe36ca2bf61d5c6eb6d895b6527e3f05071e", size = 424657, upload-time = "2025-10-08T09:15:17.825Z" }, + { url = "https://files.pythonhosted.org/packages/38/f8/4398c46863b093252fe67368b44edc6c13b17f4e6b0e4929dbf0bdb13f23/msgpack-1.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fffee09044073e69f2bad787071aeec727183e7580443dfeb8556cbf1978d162", size = 402668, upload-time = "2025-10-08T09:15:19.003Z" }, + { url = "https://files.pythonhosted.org/packages/28/ce/698c1eff75626e4124b4d78e21cca0b4cc90043afb80a507626ea354ab52/msgpack-1.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5928604de9b032bc17f5099496417f113c45bc6bc21b5c6920caf34b3c428794", size = 419040, upload-time = "2025-10-08T09:15:20.183Z" }, + { url = "https://files.pythonhosted.org/packages/67/32/f3cd1667028424fa7001d82e10ee35386eea1408b93d399b09fb0aa7875f/msgpack-1.1.2-cp313-cp313-win32.whl", hash = "sha256:a7787d353595c7c7e145e2331abf8b7ff1e6673a6b974ded96e6d4ec09f00c8c", size = 65037, upload-time = "2025-10-08T09:15:21.416Z" }, + { url = "https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:a465f0dceb8e13a487e54c07d04ae3ba131c7c5b95e2612596eafde1dccf64a9", size = 72631, upload-time = "2025-10-08T09:15:22.431Z" }, + { url = "https://files.pythonhosted.org/packages/e5/db/0314e4e2db56ebcf450f277904ffd84a7988b9e5da8d0d61ab2d057df2b6/msgpack-1.1.2-cp313-cp313-win_arm64.whl", hash = "sha256:e69b39f8c0aa5ec24b57737ebee40be647035158f14ed4b40e6f150077e21a84", size = 64118, upload-time = "2025-10-08T09:15:23.402Z" }, + { url = "https://files.pythonhosted.org/packages/22/71/201105712d0a2ff07b7873ed3c220292fb2ea5120603c00c4b634bcdafb3/msgpack-1.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e23ce8d5f7aa6ea6d2a2b326b4ba46c985dbb204523759984430db7114f8aa00", size = 81127, upload-time = "2025-10-08T09:15:24.408Z" }, + { url = "https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c15b7d74c939ebe620dd8e559384be806204d73b4f9356320632d783d1f7939", size = 84981, upload-time = "2025-10-08T09:15:25.812Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a9/3536e385167b88c2cc8f4424c49e28d49a6fc35206d4a8060f136e71f94c/msgpack-1.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99e2cb7b9031568a2a5c73aa077180f93dd2e95b4f8d3b8e14a73ae94a9e667e", size = 411885, upload-time = "2025-10-08T09:15:27.22Z" }, + { url = "https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:180759d89a057eab503cf62eeec0aa61c4ea1200dee709f3a8e9397dbb3b6931", size = 419658, upload-time = "2025-10-08T09:15:28.4Z" }, + { url = "https://files.pythonhosted.org/packages/3b/ef/2b92e286366500a09a67e03496ee8b8ba00562797a52f3c117aa2b29514b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:04fb995247a6e83830b62f0b07bf36540c213f6eac8e851166d8d86d83cbd014", size = 403290, upload-time = "2025-10-08T09:15:29.764Z" }, + { url = "https://files.pythonhosted.org/packages/78/90/e0ea7990abea5764e4655b8177aa7c63cdfa89945b6e7641055800f6c16b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8e22ab046fa7ede9e36eeb4cfad44d46450f37bb05d5ec482b02868f451c95e2", size = 415234, upload-time = "2025-10-08T09:15:31.022Z" }, + { url = "https://files.pythonhosted.org/packages/72/4e/9390aed5db983a2310818cd7d3ec0aecad45e1f7007e0cda79c79507bb0d/msgpack-1.1.2-cp314-cp314-win32.whl", hash = "sha256:80a0ff7d4abf5fecb995fcf235d4064b9a9a8a40a3ab80999e6ac1e30b702717", size = 66391, upload-time = "2025-10-08T09:15:32.265Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:9ade919fac6a3e7260b7f64cea89df6bec59104987cbea34d34a2fa15d74310b", size = 73787, upload-time = "2025-10-08T09:15:33.219Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b0/9d9f667ab48b16ad4115c1935d94023b82b3198064cb84a123e97f7466c1/msgpack-1.1.2-cp314-cp314-win_arm64.whl", hash = "sha256:59415c6076b1e30e563eb732e23b994a61c159cec44deaf584e5cc1dd662f2af", size = 66453, upload-time = "2025-10-08T09:15:34.225Z" }, + { url = "https://files.pythonhosted.org/packages/16/67/93f80545eb1792b61a217fa7f06d5e5cb9e0055bed867f43e2b8e012e137/msgpack-1.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:897c478140877e5307760b0ea66e0932738879e7aa68144d9b78ea4c8302a84a", size = 85264, upload-time = "2025-10-08T09:15:35.61Z" }, + { url = "https://files.pythonhosted.org/packages/87/1c/33c8a24959cf193966ef11a6f6a2995a65eb066bd681fd085afd519a57ce/msgpack-1.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a668204fa43e6d02f89dbe79a30b0d67238d9ec4c5bd8a940fc3a004a47b721b", size = 89076, upload-time = "2025-10-08T09:15:36.619Z" }, + { url = "https://files.pythonhosted.org/packages/fc/6b/62e85ff7193663fbea5c0254ef32f0c77134b4059f8da89b958beb7696f3/msgpack-1.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5559d03930d3aa0f3aacb4c42c776af1a2ace2611871c84a75afe436695e6245", size = 435242, upload-time = "2025-10-08T09:15:37.647Z" }, + { url = "https://files.pythonhosted.org/packages/c1/47/5c74ecb4cc277cf09f64e913947871682ffa82b3b93c8dad68083112f412/msgpack-1.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:70c5a7a9fea7f036b716191c29047374c10721c389c21e9ffafad04df8c52c90", size = 432509, upload-time = "2025-10-08T09:15:38.794Z" }, + { url = "https://files.pythonhosted.org/packages/24/a4/e98ccdb56dc4e98c929a3f150de1799831c0a800583cde9fa022fa90602d/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f2cb069d8b981abc72b41aea1c580ce92d57c673ec61af4c500153a626cb9e20", size = 415957, upload-time = "2025-10-08T09:15:40.238Z" }, + { url = "https://files.pythonhosted.org/packages/da/28/6951f7fb67bc0a4e184a6b38ab71a92d9ba58080b27a77d3e2fb0be5998f/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d62ce1f483f355f61adb5433ebfd8868c5f078d1a52d042b0a998682b4fa8c27", size = 422910, upload-time = "2025-10-08T09:15:41.505Z" }, + { url = "https://files.pythonhosted.org/packages/f0/03/42106dcded51f0a0b5284d3ce30a671e7bd3f7318d122b2ead66ad289fed/msgpack-1.1.2-cp314-cp314t-win32.whl", hash = "sha256:1d1418482b1ee984625d88aa9585db570180c286d942da463533b238b98b812b", size = 75197, upload-time = "2025-10-08T09:15:42.954Z" }, + { url = "https://files.pythonhosted.org/packages/15/86/d0071e94987f8db59d4eeb386ddc64d0bb9b10820a8d82bcd3e53eeb2da6/msgpack-1.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:5a46bf7e831d09470ad92dff02b8b1ac92175ca36b087f904a0519857c6be3ff", size = 85772, upload-time = "2025-10-08T09:15:43.954Z" }, + { url = "https://files.pythonhosted.org/packages/81/f2/08ace4142eb281c12701fc3b93a10795e4d4dc7f753911d836675050f886/msgpack-1.1.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d99ef64f349d5ec3293688e91486c5fdb925ed03807f64d98d205d2713c60b46", size = 70868, upload-time = "2025-10-08T09:15:44.959Z" }, +] + +[[package]] +name = "multidict" +version = "6.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/63/7bdd4adc330abcca54c85728db2327130e49e52e8c3ce685cec44e0f2e9f/multidict-6.7.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9f474ad5acda359c8758c8accc22032c6abe6dc87a8be2440d097785e27a9349", size = 77153, upload-time = "2025-10-06T14:48:26.409Z" }, + { url = "https://files.pythonhosted.org/packages/3f/bb/b6c35ff175ed1a3142222b78455ee31be71a8396ed3ab5280fbe3ebe4e85/multidict-6.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b7a9db5a870f780220e931d0002bbfd88fb53aceb6293251e2c839415c1b20e", size = 44993, upload-time = "2025-10-06T14:48:28.4Z" }, + { url = "https://files.pythonhosted.org/packages/e0/1f/064c77877c5fa6df6d346e68075c0f6998547afe952d6471b4c5f6a7345d/multidict-6.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03ca744319864e92721195fa28c7a3b2bc7b686246b35e4078c1e4d0eb5466d3", size = 44607, upload-time = "2025-10-06T14:48:29.581Z" }, + { url = "https://files.pythonhosted.org/packages/04/7a/bf6aa92065dd47f287690000b3d7d332edfccb2277634cadf6a810463c6a/multidict-6.7.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f0e77e3c0008bc9316e662624535b88d360c3a5d3f81e15cf12c139a75250046", size = 241847, upload-time = "2025-10-06T14:48:32.107Z" }, + { url = "https://files.pythonhosted.org/packages/94/39/297a8de920f76eda343e4ce05f3b489f0ab3f9504f2576dfb37b7c08ca08/multidict-6.7.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08325c9e5367aa379a3496aa9a022fe8837ff22e00b94db256d3a1378c76ab32", size = 242616, upload-time = "2025-10-06T14:48:34.054Z" }, + { url = "https://files.pythonhosted.org/packages/39/3a/d0eee2898cfd9d654aea6cb8c4addc2f9756e9a7e09391cfe55541f917f7/multidict-6.7.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e2862408c99f84aa571ab462d25236ef9cb12a602ea959ba9c9009a54902fc73", size = 222333, upload-time = "2025-10-06T14:48:35.9Z" }, + { url = "https://files.pythonhosted.org/packages/05/48/3b328851193c7a4240815b71eea165b49248867bbb6153a0aee227a0bb47/multidict-6.7.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4d72a9a2d885f5c208b0cb91ff2ed43636bb7e345ec839ff64708e04f69a13cc", size = 253239, upload-time = "2025-10-06T14:48:37.302Z" }, + { url = "https://files.pythonhosted.org/packages/b1/ca/0706a98c8d126a89245413225ca4a3fefc8435014de309cf8b30acb68841/multidict-6.7.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:478cc36476687bac1514d651cbbaa94b86b0732fb6855c60c673794c7dd2da62", size = 251618, upload-time = "2025-10-06T14:48:38.963Z" }, + { url = "https://files.pythonhosted.org/packages/5e/4f/9c7992f245554d8b173f6f0a048ad24b3e645d883f096857ec2c0822b8bd/multidict-6.7.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6843b28b0364dc605f21481c90fadb5f60d9123b442eb8a726bb74feef588a84", size = 241655, upload-time = "2025-10-06T14:48:40.312Z" }, + { url = "https://files.pythonhosted.org/packages/31/79/26a85991ae67efd1c0b1fc2e0c275b8a6aceeb155a68861f63f87a798f16/multidict-6.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23bfeee5316266e5ee2d625df2d2c602b829435fc3a235c2ba2131495706e4a0", size = 239245, upload-time = "2025-10-06T14:48:41.848Z" }, + { url = "https://files.pythonhosted.org/packages/14/1e/75fa96394478930b79d0302eaf9a6c69f34005a1a5251ac8b9c336486ec9/multidict-6.7.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:680878b9f3d45c31e1f730eef731f9b0bc1da456155688c6745ee84eb818e90e", size = 233523, upload-time = "2025-10-06T14:48:43.749Z" }, + { url = "https://files.pythonhosted.org/packages/b2/5e/085544cb9f9c4ad2b5d97467c15f856df8d9bac410cffd5c43991a5d878b/multidict-6.7.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:eb866162ef2f45063acc7a53a88ef6fe8bf121d45c30ea3c9cd87ce7e191a8d4", size = 243129, upload-time = "2025-10-06T14:48:45.225Z" }, + { url = "https://files.pythonhosted.org/packages/b9/c3/e9d9e2f20c9474e7a8fcef28f863c5cbd29bb5adce6b70cebe8bdad0039d/multidict-6.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:df0e3bf7993bdbeca5ac25aa859cf40d39019e015c9c91809ba7093967f7a648", size = 248999, upload-time = "2025-10-06T14:48:46.703Z" }, + { url = "https://files.pythonhosted.org/packages/b5/3f/df171b6efa3239ae33b97b887e42671cd1d94d460614bfb2c30ffdab3b95/multidict-6.7.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:661709cdcd919a2ece2234f9bae7174e5220c80b034585d7d8a755632d3e2111", size = 243711, upload-time = "2025-10-06T14:48:48.146Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2f/9b5564888c4e14b9af64c54acf149263721a283aaf4aa0ae89b091d5d8c1/multidict-6.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:096f52730c3fb8ed419db2d44391932b63891b2c5ed14850a7e215c0ba9ade36", size = 237504, upload-time = "2025-10-06T14:48:49.447Z" }, + { url = "https://files.pythonhosted.org/packages/6c/3a/0bd6ca0f7d96d790542d591c8c3354c1e1b6bfd2024d4d92dc3d87485ec7/multidict-6.7.0-cp310-cp310-win32.whl", hash = "sha256:afa8a2978ec65d2336305550535c9c4ff50ee527914328c8677b3973ade52b85", size = 41422, upload-time = "2025-10-06T14:48:50.789Z" }, + { url = "https://files.pythonhosted.org/packages/00/35/f6a637ea2c75f0d3b7c7d41b1189189acff0d9deeb8b8f35536bb30f5e33/multidict-6.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:b15b3afff74f707b9275d5ba6a91ae8f6429c3ffb29bbfd216b0b375a56f13d7", size = 46050, upload-time = "2025-10-06T14:48:51.938Z" }, + { url = "https://files.pythonhosted.org/packages/e7/b8/f7bf8329b39893d02d9d95cf610c75885d12fc0f402b1c894e1c8e01c916/multidict-6.7.0-cp310-cp310-win_arm64.whl", hash = "sha256:4b73189894398d59131a66ff157837b1fafea9974be486d036bb3d32331fdbf0", size = 43153, upload-time = "2025-10-06T14:48:53.146Z" }, + { url = "https://files.pythonhosted.org/packages/34/9e/5c727587644d67b2ed479041e4b1c58e30afc011e3d45d25bbe35781217c/multidict-6.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4d409aa42a94c0b3fa617708ef5276dfe81012ba6753a0370fcc9d0195d0a1fc", size = 76604, upload-time = "2025-10-06T14:48:54.277Z" }, + { url = "https://files.pythonhosted.org/packages/17/e4/67b5c27bd17c085a5ea8f1ec05b8a3e5cba0ca734bfcad5560fb129e70ca/multidict-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14c9e076eede3b54c636f8ce1c9c252b5f057c62131211f0ceeec273810c9721", size = 44715, upload-time = "2025-10-06T14:48:55.445Z" }, + { url = "https://files.pythonhosted.org/packages/4d/e1/866a5d77be6ea435711bef2a4291eed11032679b6b28b56b4776ab06ba3e/multidict-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c09703000a9d0fa3c3404b27041e574cc7f4df4c6563873246d0e11812a94b6", size = 44332, upload-time = "2025-10-06T14:48:56.706Z" }, + { url = "https://files.pythonhosted.org/packages/31/61/0c2d50241ada71ff61a79518db85ada85fdabfcf395d5968dae1cbda04e5/multidict-6.7.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a265acbb7bb33a3a2d626afbe756371dce0279e7b17f4f4eda406459c2b5ff1c", size = 245212, upload-time = "2025-10-06T14:48:58.042Z" }, + { url = "https://files.pythonhosted.org/packages/ac/e0/919666a4e4b57fff1b57f279be1c9316e6cdc5de8a8b525d76f6598fefc7/multidict-6.7.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51cb455de290ae462593e5b1cb1118c5c22ea7f0d3620d9940bf695cea5a4bd7", size = 246671, upload-time = "2025-10-06T14:49:00.004Z" }, + { url = "https://files.pythonhosted.org/packages/a1/cc/d027d9c5a520f3321b65adea289b965e7bcbd2c34402663f482648c716ce/multidict-6.7.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:db99677b4457c7a5c5a949353e125ba72d62b35f74e26da141530fbb012218a7", size = 225491, upload-time = "2025-10-06T14:49:01.393Z" }, + { url = "https://files.pythonhosted.org/packages/75/c4/bbd633980ce6155a28ff04e6a6492dd3335858394d7bb752d8b108708558/multidict-6.7.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f470f68adc395e0183b92a2f4689264d1ea4b40504a24d9882c27375e6662bb9", size = 257322, upload-time = "2025-10-06T14:49:02.745Z" }, + { url = "https://files.pythonhosted.org/packages/4c/6d/d622322d344f1f053eae47e033b0b3f965af01212de21b10bcf91be991fb/multidict-6.7.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0db4956f82723cc1c270de9c6e799b4c341d327762ec78ef82bb962f79cc07d8", size = 254694, upload-time = "2025-10-06T14:49:04.15Z" }, + { url = "https://files.pythonhosted.org/packages/a8/9f/78f8761c2705d4c6d7516faed63c0ebdac569f6db1bef95e0d5218fdc146/multidict-6.7.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3e56d780c238f9e1ae66a22d2adf8d16f485381878250db8d496623cd38b22bd", size = 246715, upload-time = "2025-10-06T14:49:05.967Z" }, + { url = "https://files.pythonhosted.org/packages/78/59/950818e04f91b9c2b95aab3d923d9eabd01689d0dcd889563988e9ea0fd8/multidict-6.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9d14baca2ee12c1a64740d4531356ba50b82543017f3ad6de0deb943c5979abb", size = 243189, upload-time = "2025-10-06T14:49:07.37Z" }, + { url = "https://files.pythonhosted.org/packages/7a/3d/77c79e1934cad2ee74991840f8a0110966d9599b3af95964c0cd79bb905b/multidict-6.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:295a92a76188917c7f99cda95858c822f9e4aae5824246bba9b6b44004ddd0a6", size = 237845, upload-time = "2025-10-06T14:49:08.759Z" }, + { url = "https://files.pythonhosted.org/packages/63/1b/834ce32a0a97a3b70f86437f685f880136677ac00d8bce0027e9fd9c2db7/multidict-6.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39f1719f57adbb767ef592a50ae5ebb794220d1188f9ca93de471336401c34d2", size = 246374, upload-time = "2025-10-06T14:49:10.574Z" }, + { url = "https://files.pythonhosted.org/packages/23/ef/43d1c3ba205b5dec93dc97f3fba179dfa47910fc73aaaea4f7ceb41cec2a/multidict-6.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:0a13fb8e748dfc94749f622de065dd5c1def7e0d2216dba72b1d8069a389c6ff", size = 253345, upload-time = "2025-10-06T14:49:12.331Z" }, + { url = "https://files.pythonhosted.org/packages/6b/03/eaf95bcc2d19ead522001f6a650ef32811aa9e3624ff0ad37c445c7a588c/multidict-6.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e3aa16de190d29a0ea1b48253c57d99a68492c8dd8948638073ab9e74dc9410b", size = 246940, upload-time = "2025-10-06T14:49:13.821Z" }, + { url = "https://files.pythonhosted.org/packages/e8/df/ec8a5fd66ea6cd6f525b1fcbb23511b033c3e9bc42b81384834ffa484a62/multidict-6.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a048ce45dcdaaf1defb76b2e684f997fb5abf74437b6cb7b22ddad934a964e34", size = 242229, upload-time = "2025-10-06T14:49:15.603Z" }, + { url = "https://files.pythonhosted.org/packages/8a/a2/59b405d59fd39ec86d1142630e9049243015a5f5291ba49cadf3c090c541/multidict-6.7.0-cp311-cp311-win32.whl", hash = "sha256:a90af66facec4cebe4181b9e62a68be65e45ac9b52b67de9eec118701856e7ff", size = 41308, upload-time = "2025-10-06T14:49:16.871Z" }, + { url = "https://files.pythonhosted.org/packages/32/0f/13228f26f8b882c34da36efa776c3b7348455ec383bab4a66390e42963ae/multidict-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:95b5ffa4349df2887518bb839409bcf22caa72d82beec453216802f475b23c81", size = 46037, upload-time = "2025-10-06T14:49:18.457Z" }, + { url = "https://files.pythonhosted.org/packages/84/1f/68588e31b000535a3207fd3c909ebeec4fb36b52c442107499c18a896a2a/multidict-6.7.0-cp311-cp311-win_arm64.whl", hash = "sha256:329aa225b085b6f004a4955271a7ba9f1087e39dcb7e65f6284a988264a63912", size = 43023, upload-time = "2025-10-06T14:49:19.648Z" }, + { url = "https://files.pythonhosted.org/packages/c2/9e/9f61ac18d9c8b475889f32ccfa91c9f59363480613fc807b6e3023d6f60b/multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", size = 76877, upload-time = "2025-10-06T14:49:20.884Z" }, + { url = "https://files.pythonhosted.org/packages/38/6f/614f09a04e6184f8824268fce4bc925e9849edfa654ddd59f0b64508c595/multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", size = 45467, upload-time = "2025-10-06T14:49:22.054Z" }, + { url = "https://files.pythonhosted.org/packages/b3/93/c4f67a436dd026f2e780c433277fff72be79152894d9fc36f44569cab1a6/multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", size = 43834, upload-time = "2025-10-06T14:49:23.566Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f5/013798161ca665e4a422afbc5e2d9e4070142a9ff8905e482139cd09e4d0/multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", size = 250545, upload-time = "2025-10-06T14:49:24.882Z" }, + { url = "https://files.pythonhosted.org/packages/71/2f/91dbac13e0ba94669ea5119ba267c9a832f0cb65419aca75549fcf09a3dc/multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", size = 258305, upload-time = "2025-10-06T14:49:26.778Z" }, + { url = "https://files.pythonhosted.org/packages/ef/b0/754038b26f6e04488b48ac621f779c341338d78503fb45403755af2df477/multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", size = 242363, upload-time = "2025-10-06T14:49:28.562Z" }, + { url = "https://files.pythonhosted.org/packages/87/15/9da40b9336a7c9fa606c4cf2ed80a649dffeb42b905d4f63a1d7eb17d746/multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", size = 268375, upload-time = "2025-10-06T14:49:29.96Z" }, + { url = "https://files.pythonhosted.org/packages/82/72/c53fcade0cc94dfaad583105fd92b3a783af2091eddcb41a6d5a52474000/multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", size = 269346, upload-time = "2025-10-06T14:49:31.404Z" }, + { url = "https://files.pythonhosted.org/packages/0d/e2/9baffdae21a76f77ef8447f1a05a96ec4bc0a24dae08767abc0a2fe680b8/multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", size = 256107, upload-time = "2025-10-06T14:49:32.974Z" }, + { url = "https://files.pythonhosted.org/packages/3c/06/3f06f611087dc60d65ef775f1fb5aca7c6d61c6db4990e7cda0cef9b1651/multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", size = 253592, upload-time = "2025-10-06T14:49:34.52Z" }, + { url = "https://files.pythonhosted.org/packages/20/24/54e804ec7945b6023b340c412ce9c3f81e91b3bf5fa5ce65558740141bee/multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", size = 251024, upload-time = "2025-10-06T14:49:35.956Z" }, + { url = "https://files.pythonhosted.org/packages/14/48/011cba467ea0b17ceb938315d219391d3e421dfd35928e5dbdc3f4ae76ef/multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", size = 251484, upload-time = "2025-10-06T14:49:37.631Z" }, + { url = "https://files.pythonhosted.org/packages/0d/2f/919258b43bb35b99fa127435cfb2d91798eb3a943396631ef43e3720dcf4/multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", size = 263579, upload-time = "2025-10-06T14:49:39.502Z" }, + { url = "https://files.pythonhosted.org/packages/31/22/a0e884d86b5242b5a74cf08e876bdf299e413016b66e55511f7a804a366e/multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", size = 259654, upload-time = "2025-10-06T14:49:41.32Z" }, + { url = "https://files.pythonhosted.org/packages/b2/e5/17e10e1b5c5f5a40f2fcbb45953c9b215f8a4098003915e46a93f5fcaa8f/multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", size = 251511, upload-time = "2025-10-06T14:49:46.021Z" }, + { url = "https://files.pythonhosted.org/packages/e3/9a/201bb1e17e7af53139597069c375e7b0dcbd47594604f65c2d5359508566/multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", size = 41895, upload-time = "2025-10-06T14:49:48.718Z" }, + { url = "https://files.pythonhosted.org/packages/46/e2/348cd32faad84eaf1d20cce80e2bb0ef8d312c55bca1f7fa9865e7770aaf/multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", size = 46073, upload-time = "2025-10-06T14:49:50.28Z" }, + { url = "https://files.pythonhosted.org/packages/25/ec/aad2613c1910dce907480e0c3aa306905830f25df2e54ccc9dea450cb5aa/multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", size = 43226, upload-time = "2025-10-06T14:49:52.304Z" }, + { url = "https://files.pythonhosted.org/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" }, + { url = "https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" }, + { url = "https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" }, + { url = "https://files.pythonhosted.org/packages/75/3f/e2639e80325af0b6c6febdf8e57cc07043ff15f57fa1ef808f4ccb5ac4cd/multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", size = 249342, upload-time = "2025-10-06T14:49:58.368Z" }, + { url = "https://files.pythonhosted.org/packages/5d/cc/84e0585f805cbeaa9cbdaa95f9a3d6aed745b9d25700623ac89a6ecff400/multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", size = 257082, upload-time = "2025-10-06T14:49:59.89Z" }, + { url = "https://files.pythonhosted.org/packages/b0/9c/ac851c107c92289acbbf5cfb485694084690c1b17e555f44952c26ddc5bd/multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", size = 240704, upload-time = "2025-10-06T14:50:01.485Z" }, + { url = "https://files.pythonhosted.org/packages/50/cc/5f93e99427248c09da95b62d64b25748a5f5c98c7c2ab09825a1d6af0e15/multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", size = 266355, upload-time = "2025-10-06T14:50:02.955Z" }, + { url = "https://files.pythonhosted.org/packages/ec/0c/2ec1d883ceb79c6f7f6d7ad90c919c898f5d1c6ea96d322751420211e072/multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", size = 267259, upload-time = "2025-10-06T14:50:04.446Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", size = 254903, upload-time = "2025-10-06T14:50:05.98Z" }, + { url = "https://files.pythonhosted.org/packages/06/c9/11ea263ad0df7dfabcad404feb3c0dd40b131bc7f232d5537f2fb1356951/multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", size = 252365, upload-time = "2025-10-06T14:50:07.511Z" }, + { url = "https://files.pythonhosted.org/packages/41/88/d714b86ee2c17d6e09850c70c9d310abac3d808ab49dfa16b43aba9d53fd/multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", size = 250062, upload-time = "2025-10-06T14:50:09.074Z" }, + { url = "https://files.pythonhosted.org/packages/15/fe/ad407bb9e818c2b31383f6131ca19ea7e35ce93cf1310fce69f12e89de75/multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", size = 249683, upload-time = "2025-10-06T14:50:10.714Z" }, + { url = "https://files.pythonhosted.org/packages/8c/a4/a89abdb0229e533fb925e7c6e5c40201c2873efebc9abaf14046a4536ee6/multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", size = 261254, upload-time = "2025-10-06T14:50:12.28Z" }, + { url = "https://files.pythonhosted.org/packages/8d/aa/0e2b27bd88b40a4fb8dc53dd74eecac70edaa4c1dd0707eb2164da3675b3/multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", size = 257967, upload-time = "2025-10-06T14:50:14.16Z" }, + { url = "https://files.pythonhosted.org/packages/d0/8e/0c67b7120d5d5f6d874ed85a085f9dc770a7f9d8813e80f44a9fec820bb7/multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", size = 250085, upload-time = "2025-10-06T14:50:15.639Z" }, + { url = "https://files.pythonhosted.org/packages/ba/55/b73e1d624ea4b8fd4dd07a3bb70f6e4c7c6c5d9d640a41c6ffe5cdbd2a55/multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", size = 41713, upload-time = "2025-10-06T14:50:17.066Z" }, + { url = "https://files.pythonhosted.org/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", size = 45915, upload-time = "2025-10-06T14:50:18.264Z" }, + { url = "https://files.pythonhosted.org/packages/31/2a/8987831e811f1184c22bc2e45844934385363ee61c0a2dcfa8f71b87e608/multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", size = 43077, upload-time = "2025-10-06T14:50:19.853Z" }, + { url = "https://files.pythonhosted.org/packages/e8/68/7b3a5170a382a340147337b300b9eb25a9ddb573bcdfff19c0fa3f31ffba/multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", size = 83114, upload-time = "2025-10-06T14:50:21.223Z" }, + { url = "https://files.pythonhosted.org/packages/55/5c/3fa2d07c84df4e302060f555bbf539310980362236ad49f50eeb0a1c1eb9/multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", size = 48442, upload-time = "2025-10-06T14:50:22.871Z" }, + { url = "https://files.pythonhosted.org/packages/fc/56/67212d33239797f9bd91962bb899d72bb0f4c35a8652dcdb8ed049bef878/multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", size = 46885, upload-time = "2025-10-06T14:50:24.258Z" }, + { url = "https://files.pythonhosted.org/packages/46/d1/908f896224290350721597a61a69cd19b89ad8ee0ae1f38b3f5cd12ea2ac/multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", size = 242588, upload-time = "2025-10-06T14:50:25.716Z" }, + { url = "https://files.pythonhosted.org/packages/ab/67/8604288bbd68680eee0ab568fdcb56171d8b23a01bcd5cb0c8fedf6e5d99/multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", size = 249966, upload-time = "2025-10-06T14:50:28.192Z" }, + { url = "https://files.pythonhosted.org/packages/20/33/9228d76339f1ba51e3efef7da3ebd91964d3006217aae13211653193c3ff/multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", size = 228618, upload-time = "2025-10-06T14:50:29.82Z" }, + { url = "https://files.pythonhosted.org/packages/f8/2d/25d9b566d10cab1c42b3b9e5b11ef79c9111eaf4463b8c257a3bd89e0ead/multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", size = 257539, upload-time = "2025-10-06T14:50:31.731Z" }, + { url = "https://files.pythonhosted.org/packages/b6/b1/8d1a965e6637fc33de3c0d8f414485c2b7e4af00f42cab3d84e7b955c222/multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", size = 256345, upload-time = "2025-10-06T14:50:33.26Z" }, + { url = "https://files.pythonhosted.org/packages/ba/0c/06b5a8adbdeedada6f4fb8d8f193d44a347223b11939b42953eeb6530b6b/multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", size = 247934, upload-time = "2025-10-06T14:50:34.808Z" }, + { url = "https://files.pythonhosted.org/packages/8f/31/b2491b5fe167ca044c6eb4b8f2c9f3b8a00b24c432c365358eadac5d7625/multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", size = 245243, upload-time = "2025-10-06T14:50:36.436Z" }, + { url = "https://files.pythonhosted.org/packages/61/1a/982913957cb90406c8c94f53001abd9eafc271cb3e70ff6371590bec478e/multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", size = 235878, upload-time = "2025-10-06T14:50:37.953Z" }, + { url = "https://files.pythonhosted.org/packages/be/c0/21435d804c1a1cf7a2608593f4d19bca5bcbd7a81a70b253fdd1c12af9c0/multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", size = 243452, upload-time = "2025-10-06T14:50:39.574Z" }, + { url = "https://files.pythonhosted.org/packages/54/0a/4349d540d4a883863191be6eb9a928846d4ec0ea007d3dcd36323bb058ac/multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", size = 252312, upload-time = "2025-10-06T14:50:41.612Z" }, + { url = "https://files.pythonhosted.org/packages/26/64/d5416038dbda1488daf16b676e4dbfd9674dde10a0cc8f4fc2b502d8125d/multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", size = 246935, upload-time = "2025-10-06T14:50:43.972Z" }, + { url = "https://files.pythonhosted.org/packages/9f/8c/8290c50d14e49f35e0bd4abc25e1bc7711149ca9588ab7d04f886cdf03d9/multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", size = 243385, upload-time = "2025-10-06T14:50:45.648Z" }, + { url = "https://files.pythonhosted.org/packages/ef/a0/f83ae75e42d694b3fbad3e047670e511c138be747bc713cf1b10d5096416/multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", size = 47777, upload-time = "2025-10-06T14:50:47.154Z" }, + { url = "https://files.pythonhosted.org/packages/dc/80/9b174a92814a3830b7357307a792300f42c9e94664b01dee8e457551fa66/multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", size = 53104, upload-time = "2025-10-06T14:50:48.851Z" }, + { url = "https://files.pythonhosted.org/packages/cc/28/04baeaf0428d95bb7a7bea0e691ba2f31394338ba424fb0679a9ed0f4c09/multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", size = 45503, upload-time = "2025-10-06T14:50:50.16Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b1/3da6934455dd4b261d4c72f897e3a5728eba81db59959f3a639245891baa/multidict-6.7.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842", size = 75128, upload-time = "2025-10-06T14:50:51.92Z" }, + { url = "https://files.pythonhosted.org/packages/14/2c/f069cab5b51d175a1a2cb4ccdf7a2c2dabd58aa5bd933fa036a8d15e2404/multidict-6.7.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b", size = 44410, upload-time = "2025-10-06T14:50:53.275Z" }, + { url = "https://files.pythonhosted.org/packages/42/e2/64bb41266427af6642b6b128e8774ed84c11b80a90702c13ac0a86bb10cc/multidict-6.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38", size = 43205, upload-time = "2025-10-06T14:50:54.911Z" }, + { url = "https://files.pythonhosted.org/packages/02/68/6b086fef8a3f1a8541b9236c594f0c9245617c29841f2e0395d979485cde/multidict-6.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128", size = 245084, upload-time = "2025-10-06T14:50:56.369Z" }, + { url = "https://files.pythonhosted.org/packages/15/ee/f524093232007cd7a75c1d132df70f235cfd590a7c9eaccd7ff422ef4ae8/multidict-6.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34", size = 252667, upload-time = "2025-10-06T14:50:57.991Z" }, + { url = "https://files.pythonhosted.org/packages/02/a5/eeb3f43ab45878f1895118c3ef157a480db58ede3f248e29b5354139c2c9/multidict-6.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99", size = 233590, upload-time = "2025-10-06T14:50:59.589Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/76d02f8270b97269d7e3dbd45644b1785bda457b474315f8cf999525a193/multidict-6.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202", size = 264112, upload-time = "2025-10-06T14:51:01.183Z" }, + { url = "https://files.pythonhosted.org/packages/76/0b/c28a70ecb58963847c2a8efe334904cd254812b10e535aefb3bcce513918/multidict-6.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1", size = 261194, upload-time = "2025-10-06T14:51:02.794Z" }, + { url = "https://files.pythonhosted.org/packages/b4/63/2ab26e4209773223159b83aa32721b4021ffb08102f8ac7d689c943fded1/multidict-6.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3", size = 248510, upload-time = "2025-10-06T14:51:04.724Z" }, + { url = "https://files.pythonhosted.org/packages/93/cd/06c1fa8282af1d1c46fd55c10a7930af652afdce43999501d4d68664170c/multidict-6.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d", size = 248395, upload-time = "2025-10-06T14:51:06.306Z" }, + { url = "https://files.pythonhosted.org/packages/99/ac/82cb419dd6b04ccf9e7e61befc00c77614fc8134362488b553402ecd55ce/multidict-6.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6", size = 239520, upload-time = "2025-10-06T14:51:08.091Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f3/a0f9bf09493421bd8716a362e0cd1d244f5a6550f5beffdd6b47e885b331/multidict-6.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7", size = 245479, upload-time = "2025-10-06T14:51:10.365Z" }, + { url = "https://files.pythonhosted.org/packages/8d/01/476d38fc73a212843f43c852b0eee266b6971f0e28329c2184a8df90c376/multidict-6.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb", size = 258903, upload-time = "2025-10-06T14:51:12.466Z" }, + { url = "https://files.pythonhosted.org/packages/49/6d/23faeb0868adba613b817d0e69c5f15531b24d462af8012c4f6de4fa8dc3/multidict-6.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f", size = 252333, upload-time = "2025-10-06T14:51:14.48Z" }, + { url = "https://files.pythonhosted.org/packages/1e/cc/48d02ac22b30fa247f7dad82866e4b1015431092f4ba6ebc7e77596e0b18/multidict-6.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f", size = 243411, upload-time = "2025-10-06T14:51:16.072Z" }, + { url = "https://files.pythonhosted.org/packages/4a/03/29a8bf5a18abf1fe34535c88adbdfa88c9fb869b5a3b120692c64abe8284/multidict-6.7.0-cp314-cp314-win32.whl", hash = "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885", size = 40940, upload-time = "2025-10-06T14:51:17.544Z" }, + { url = "https://files.pythonhosted.org/packages/82/16/7ed27b680791b939de138f906d5cf2b4657b0d45ca6f5dd6236fdddafb1a/multidict-6.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c", size = 45087, upload-time = "2025-10-06T14:51:18.875Z" }, + { url = "https://files.pythonhosted.org/packages/cd/3c/e3e62eb35a1950292fe39315d3c89941e30a9d07d5d2df42965ab041da43/multidict-6.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000", size = 42368, upload-time = "2025-10-06T14:51:20.225Z" }, + { url = "https://files.pythonhosted.org/packages/8b/40/cd499bd0dbc5f1136726db3153042a735fffd0d77268e2ee20d5f33c010f/multidict-6.7.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63", size = 82326, upload-time = "2025-10-06T14:51:21.588Z" }, + { url = "https://files.pythonhosted.org/packages/13/8a/18e031eca251c8df76daf0288e6790561806e439f5ce99a170b4af30676b/multidict-6.7.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718", size = 48065, upload-time = "2025-10-06T14:51:22.93Z" }, + { url = "https://files.pythonhosted.org/packages/40/71/5e6701277470a87d234e433fb0a3a7deaf3bcd92566e421e7ae9776319de/multidict-6.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2", size = 46475, upload-time = "2025-10-06T14:51:24.352Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6a/bab00cbab6d9cfb57afe1663318f72ec28289ea03fd4e8236bb78429893a/multidict-6.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e", size = 239324, upload-time = "2025-10-06T14:51:25.822Z" }, + { url = "https://files.pythonhosted.org/packages/2a/5f/8de95f629fc22a7769ade8b41028e3e5a822c1f8904f618d175945a81ad3/multidict-6.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064", size = 246877, upload-time = "2025-10-06T14:51:27.604Z" }, + { url = "https://files.pythonhosted.org/packages/23/b4/38881a960458f25b89e9f4a4fdcb02ac101cfa710190db6e5528841e67de/multidict-6.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e", size = 225824, upload-time = "2025-10-06T14:51:29.664Z" }, + { url = "https://files.pythonhosted.org/packages/1e/39/6566210c83f8a261575f18e7144736059f0c460b362e96e9cf797a24b8e7/multidict-6.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd", size = 253558, upload-time = "2025-10-06T14:51:31.684Z" }, + { url = "https://files.pythonhosted.org/packages/00/a3/67f18315100f64c269f46e6c0319fa87ba68f0f64f2b8e7fd7c72b913a0b/multidict-6.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a", size = 252339, upload-time = "2025-10-06T14:51:33.699Z" }, + { url = "https://files.pythonhosted.org/packages/c8/2a/1cb77266afee2458d82f50da41beba02159b1d6b1f7973afc9a1cad1499b/multidict-6.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96", size = 244895, upload-time = "2025-10-06T14:51:36.189Z" }, + { url = "https://files.pythonhosted.org/packages/dd/72/09fa7dd487f119b2eb9524946ddd36e2067c08510576d43ff68469563b3b/multidict-6.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e", size = 241862, upload-time = "2025-10-06T14:51:41.291Z" }, + { url = "https://files.pythonhosted.org/packages/65/92/bc1f8bd0853d8669300f732c801974dfc3702c3eeadae2f60cef54dc69d7/multidict-6.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599", size = 232376, upload-time = "2025-10-06T14:51:43.55Z" }, + { url = "https://files.pythonhosted.org/packages/09/86/ac39399e5cb9d0c2ac8ef6e10a768e4d3bc933ac808d49c41f9dc23337eb/multidict-6.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394", size = 240272, upload-time = "2025-10-06T14:51:45.265Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b6/fed5ac6b8563ec72df6cb1ea8dac6d17f0a4a1f65045f66b6d3bf1497c02/multidict-6.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38", size = 248774, upload-time = "2025-10-06T14:51:46.836Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8d/b954d8c0dc132b68f760aefd45870978deec6818897389dace00fcde32ff/multidict-6.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9", size = 242731, upload-time = "2025-10-06T14:51:48.541Z" }, + { url = "https://files.pythonhosted.org/packages/16/9d/a2dac7009125d3540c2f54e194829ea18ac53716c61b655d8ed300120b0f/multidict-6.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0", size = 240193, upload-time = "2025-10-06T14:51:50.355Z" }, + { url = "https://files.pythonhosted.org/packages/39/ca/c05f144128ea232ae2178b008d5011d4e2cea86e4ee8c85c2631b1b94802/multidict-6.7.0-cp314-cp314t-win32.whl", hash = "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13", size = 48023, upload-time = "2025-10-06T14:51:51.883Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8f/0a60e501584145588be1af5cc829265701ba3c35a64aec8e07cbb71d39bb/multidict-6.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd", size = 53507, upload-time = "2025-10-06T14:51:53.672Z" }, + { url = "https://files.pythonhosted.org/packages/7f/ae/3148b988a9c6239903e786eac19c889fab607c31d6efa7fb2147e5680f23/multidict-6.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827", size = 44804, upload-time = "2025-10-06T14:51:55.415Z" }, + { url = "https://files.pythonhosted.org/packages/b7/da/7d22601b625e241d4f23ef1ebff8acfc60da633c9e7e7922e24d10f592b3/multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", size = 12317, upload-time = "2025-10-06T14:52:29.272Z" }, +] + +[[package]] +name = "multiprocess" +version = "0.70.16" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dill" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b5/ae/04f39c5d0d0def03247c2893d6f2b83c136bf3320a2154d7b8858f2ba72d/multiprocess-0.70.16.tar.gz", hash = "sha256:161af703d4652a0e1410be6abccecde4a7ddffd19341be0a7011b94aeb171ac1", size = 1772603, upload-time = "2024-01-28T18:52:34.85Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/76/6e712a2623d146d314f17598df5de7224c85c0060ef63fd95cc15a25b3fa/multiprocess-0.70.16-pp310-pypy310_pp73-macosx_10_13_x86_64.whl", hash = "sha256:476887be10e2f59ff183c006af746cb6f1fd0eadcfd4ef49e605cbe2659920ee", size = 134980, upload-time = "2024-01-28T18:52:15.731Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ab/1e6e8009e380e22254ff539ebe117861e5bdb3bff1fc977920972237c6c7/multiprocess-0.70.16-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d951bed82c8f73929ac82c61f01a7b5ce8f3e5ef40f5b52553b4f547ce2b08ec", size = 134982, upload-time = "2024-01-28T18:52:17.783Z" }, + { url = "https://files.pythonhosted.org/packages/bc/f7/7ec7fddc92e50714ea3745631f79bd9c96424cb2702632521028e57d3a36/multiprocess-0.70.16-py310-none-any.whl", hash = "sha256:c4a9944c67bd49f823687463660a2d6daae94c289adff97e0f9d696ba6371d02", size = 134824, upload-time = "2024-01-28T18:52:26.062Z" }, + { url = "https://files.pythonhosted.org/packages/50/15/b56e50e8debaf439f44befec5b2af11db85f6e0f344c3113ae0be0593a91/multiprocess-0.70.16-py311-none-any.whl", hash = "sha256:af4cabb0dac72abfb1e794fa7855c325fd2b55a10a44628a3c1ad3311c04127a", size = 143519, upload-time = "2024-01-28T18:52:28.115Z" }, + { url = "https://files.pythonhosted.org/packages/0a/7d/a988f258104dcd2ccf1ed40fdc97e26c4ac351eeaf81d76e266c52d84e2f/multiprocess-0.70.16-py312-none-any.whl", hash = "sha256:fc0544c531920dde3b00c29863377f87e1632601092ea2daca74e4beb40faa2e", size = 146741, upload-time = "2024-01-28T18:52:29.395Z" }, + { url = "https://files.pythonhosted.org/packages/ea/89/38df130f2c799090c978b366cfdf5b96d08de5b29a4a293df7f7429fa50b/multiprocess-0.70.16-py38-none-any.whl", hash = "sha256:a71d82033454891091a226dfc319d0cfa8019a4e888ef9ca910372a446de4435", size = 132628, upload-time = "2024-01-28T18:52:30.853Z" }, + { url = "https://files.pythonhosted.org/packages/da/d9/f7f9379981e39b8c2511c9e0326d212accacb82f12fbfdc1aa2ce2a7b2b6/multiprocess-0.70.16-py39-none-any.whl", hash = "sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3", size = 133351, upload-time = "2024-01-28T18:52:31.981Z" }, +] + +[[package]] +name = "murmurhash" +version = "1.0.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/e9/02efbc6dfc2dd2085da3daacf9a8c17e8356019eceaedbfa21555e32d2af/murmurhash-1.0.13.tar.gz", hash = "sha256:737246d41ee00ff74b07b0bd1f0888be304d203ce668e642c86aa64ede30f8b7", size = 13258, upload-time = "2025-05-22T12:35:57.019Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/c3/ac14ed2aff4f18eadccf7d4e80c2361cf6e9a6a350442db9987919c4a747/murmurhash-1.0.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:136c7017e7d59ef16f065c2285bf5d30557ad8260adf47714c3c2802725e3e07", size = 26278, upload-time = "2025-05-22T12:35:10.16Z" }, + { url = "https://files.pythonhosted.org/packages/62/38/87e5f72aa96a0a816b90cd66209cda713e168d4d23b52af62fdba3c8b33c/murmurhash-1.0.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d0292f6fcd99361157fafad5c86d508f367931b7699cce1e14747364596950cb", size = 26528, upload-time = "2025-05-22T12:35:12.181Z" }, + { url = "https://files.pythonhosted.org/packages/6a/df/f74b22acf2ebf04ea24b858667836c9490e677ef29c1fe7bc993ecf4bc12/murmurhash-1.0.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12265dc748257966c62041b677201b8fa74334a2548dc27f1c7a9e78dab7c2c1", size = 120045, upload-time = "2025-05-22T12:35:13.657Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/19c48d4c5ad475e144fba5b1adf45d8a189eabde503168660e1ec5d081e8/murmurhash-1.0.13-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e411d5be64d37f2ce10a5d4d74c50bb35bd06205745b9631c4d8b1cb193e540", size = 117103, upload-time = "2025-05-22T12:35:14.899Z" }, + { url = "https://files.pythonhosted.org/packages/48/0e/3d6e009c539709f0cf643679977e2dfbd5d50e1ef49928f9a92941839482/murmurhash-1.0.13-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:da3500ad3dbf75ac9c6bc8c5fbc677d56dfc34aec0a289269939d059f194f61d", size = 118191, upload-time = "2025-05-22T12:35:16.098Z" }, + { url = "https://files.pythonhosted.org/packages/7c/8c/fab9d11bde62783d2aa7919e1ecbbf12dea7100ea61f63f55c9e0f199a6a/murmurhash-1.0.13-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b23278c5428fc14f3101f8794f38ec937da042198930073e8c86d00add0fa2f0", size = 118663, upload-time = "2025-05-22T12:35:17.847Z" }, + { url = "https://files.pythonhosted.org/packages/cf/23/322d87ab935782f2676a836ea88d92f87e58db40fb49112ba03b03d335a1/murmurhash-1.0.13-cp310-cp310-win_amd64.whl", hash = "sha256:7bc27226c0e8d9927f8e59af0dfefc93f5009e4ec3dde8da4ba7751ba19edd47", size = 24504, upload-time = "2025-05-22T12:35:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/2c/d1/9d13a02d9c8bfff10b1f68d19df206eaf2a8011defeccf7eb05ea0b8c54e/murmurhash-1.0.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b20d168370bc3ce82920121b78ab35ae244070a9b18798f4a2e8678fa03bd7e0", size = 26410, upload-time = "2025-05-22T12:35:20.786Z" }, + { url = "https://files.pythonhosted.org/packages/14/b0/3ee762e98cf9a8c2df9c8b377c326f3dd4495066d4eace9066fca46eba7a/murmurhash-1.0.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cef667d2e83bdceea3bc20c586c491fa442662ace1aea66ff5e3a18bb38268d8", size = 26679, upload-time = "2025-05-22T12:35:21.808Z" }, + { url = "https://files.pythonhosted.org/packages/39/06/24618f79cd5aac48490932e50263bddfd1ea90f7123d49bfe806a5982675/murmurhash-1.0.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:507148e50929ba1fce36898808573b9f81c763d5676f3fc6e4e832ff56b66992", size = 125970, upload-time = "2025-05-22T12:35:23.222Z" }, + { url = "https://files.pythonhosted.org/packages/e8/09/0e7afce0a422692506c85474a26fb3a03c1971b2b5f7e7745276c4b3de7f/murmurhash-1.0.13-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d50f6173d266ad165beb8bca6101d824217fc9279f9e9981f4c0245c1e7ee6", size = 123390, upload-time = "2025-05-22T12:35:24.303Z" }, + { url = "https://files.pythonhosted.org/packages/22/4c/c98f579b1a951b2bcc722a35270a2eec105c1e21585c9b314a02079e3c4d/murmurhash-1.0.13-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0f272e15a84a8ae5f8b4bc0a68f9f47be38518ddffc72405791178058e9d019a", size = 124007, upload-time = "2025-05-22T12:35:25.446Z" }, + { url = "https://files.pythonhosted.org/packages/df/f8/1b0dcebc8df8e091341617102b5b3b97deb6435f345b84f75382c290ec2c/murmurhash-1.0.13-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9423e0b0964ed1013a06c970199538c7ef9ca28c0be54798c0f1473a6591761", size = 123705, upload-time = "2025-05-22T12:35:26.709Z" }, + { url = "https://files.pythonhosted.org/packages/79/17/f2a38558e150a0669d843f75e128afb83c1a67af41885ea2acb940e18e2a/murmurhash-1.0.13-cp311-cp311-win_amd64.whl", hash = "sha256:83b81e7084b696df3d853f2c78e0c9bda6b285d643f923f1a6fa9ab145d705c5", size = 24572, upload-time = "2025-05-22T12:35:30.38Z" }, + { url = "https://files.pythonhosted.org/packages/e1/53/56ce2d8d4b9ab89557cb1d00ffce346b80a2eb2d8c7944015e5c83eacdec/murmurhash-1.0.13-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbe882e46cb3f86e092d8a1dd7a5a1c992da1ae3b39f7dd4507b6ce33dae7f92", size = 26859, upload-time = "2025-05-22T12:35:31.815Z" }, + { url = "https://files.pythonhosted.org/packages/f8/85/3a0ad54a61257c31496545ae6861515d640316f93681d1dd917e7be06634/murmurhash-1.0.13-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:52a33a12ecedc432493692c207c784b06b6427ffaa897fc90b7a76e65846478d", size = 26900, upload-time = "2025-05-22T12:35:34.267Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cd/6651de26744b50ff11c79f0c0d41244db039625de53c0467a7a52876b2d8/murmurhash-1.0.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:950403a7f0dc2d9c8d0710f07c296f2daab66299d9677d6c65d6b6fa2cb30aaa", size = 131367, upload-time = "2025-05-22T12:35:35.258Z" }, + { url = "https://files.pythonhosted.org/packages/50/6c/01ded95ddce33811c9766cae4ce32e0a54288da1d909ee2bcaa6ed13b9f1/murmurhash-1.0.13-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fde9fb5d2c106d86ff3ef2e4a9a69c2a8d23ba46e28c6b30034dc58421bc107b", size = 128943, upload-time = "2025-05-22T12:35:36.358Z" }, + { url = "https://files.pythonhosted.org/packages/ab/27/e539a9622d7bea3ae22706c1eb80d4af80f9dddd93b54d151955c2ae4011/murmurhash-1.0.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3aa55d62773745616e1ab19345dece122f6e6d09224f7be939cc5b4c513c8473", size = 129108, upload-time = "2025-05-22T12:35:37.864Z" }, + { url = "https://files.pythonhosted.org/packages/7a/84/18af5662e07d06839ad4db18ce026e6f8ef850d7b0ba92817b28dad28ba6/murmurhash-1.0.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:060dfef1b405cf02c450f182fb629f76ebe7f79657cced2db5054bc29b34938b", size = 129175, upload-time = "2025-05-22T12:35:38.928Z" }, + { url = "https://files.pythonhosted.org/packages/fe/8d/b01d3ee1f1cf3957250223b7c6ce35454f38fbf4abe236bf04a3f769341d/murmurhash-1.0.13-cp312-cp312-win_amd64.whl", hash = "sha256:a8e79627d44a6e20a6487effc30bfe1c74754c13d179106e68cc6d07941b022c", size = 24869, upload-time = "2025-05-22T12:35:40.035Z" }, + { url = "https://files.pythonhosted.org/packages/00/b4/8919dfdc4a131ad38a57b2c5de69f4bd74538bf546637ee59ebaebe6e5a4/murmurhash-1.0.13-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b8a7f8befd901379b6dc57a9e49c5188454113747ad6aa8cdd951a6048e10790", size = 26852, upload-time = "2025-05-22T12:35:41.061Z" }, + { url = "https://files.pythonhosted.org/packages/b4/32/ce78bef5d6101568bcb12f5bb5103fabcbe23723ec52e76ff66132d5dbb7/murmurhash-1.0.13-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f741aab86007510199193eee4f87c5ece92bc5a6ca7d0fe0d27335c1203dface", size = 26900, upload-time = "2025-05-22T12:35:42.097Z" }, + { url = "https://files.pythonhosted.org/packages/0c/4c/0f47c0b4f6b31a1de84d65f9573832c78cd47b4b8ce25ab5596a8238d150/murmurhash-1.0.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82614f18fa6d9d83da6bb0918f3789a3e1555d0ce12c2548153e97f79b29cfc9", size = 130033, upload-time = "2025-05-22T12:35:43.113Z" }, + { url = "https://files.pythonhosted.org/packages/e0/cb/e47233e32fb792dcc9fb18a2cf65f795d47179b29c2b4a2034689f14c707/murmurhash-1.0.13-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91f22a48b9454712e0690aa0b76cf0156a5d5a083d23ec7e209cfaeef28f56ff", size = 130619, upload-time = "2025-05-22T12:35:44.229Z" }, + { url = "https://files.pythonhosted.org/packages/8f/f1/f89911bf304ba5d385ccd346cc7fbb1c1450a24f093b592c3bfe87768467/murmurhash-1.0.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c4bc7938627b8fcb3d598fe6657cc96d1e31f4eba6a871b523c1512ab6dacb3e", size = 127643, upload-time = "2025-05-22T12:35:45.369Z" }, + { url = "https://files.pythonhosted.org/packages/a4/24/262229221f6840c1a04a46051075e99675e591571abcca6b9a8b6aa1602b/murmurhash-1.0.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58a61f1fc840f9ef704e638c39b8517bab1d21f1a9dbb6ba3ec53e41360e44ec", size = 127981, upload-time = "2025-05-22T12:35:46.503Z" }, + { url = "https://files.pythonhosted.org/packages/18/25/addbc1d28f83252732ac3e57334d42f093890b4c2cce483ba01a42bc607c/murmurhash-1.0.13-cp313-cp313-win_amd64.whl", hash = "sha256:c451a22f14c2f40e7abaea521ee24fa0e46fbec480c4304c25c946cdb6e81883", size = 24880, upload-time = "2025-05-22T12:35:47.625Z" }, +] + +[[package]] +name = "networkx" +version = "3.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/04/e6/b164f94c869d6b2c605b5128b7b0cfe912795a87fc90e78533920001f3ec/networkx-3.3.tar.gz", hash = "sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9", size = 2126579, upload-time = "2024-04-06T12:59:47.137Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl", hash = "sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2", size = 1702396, upload-time = "2024-04-06T12:59:44.283Z" }, +] + +[[package]] +name = "numpy" +version = "2.2.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" }, + { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" }, + { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" }, + { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" }, + { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" }, + { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" }, + { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" }, + { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" }, + { url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" }, + { url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" }, + { url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" }, + { url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" }, + { url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" }, + { url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" }, + { url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" }, + { url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" }, + { url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" }, + { url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" }, + { url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" }, + { url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" }, + { url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" }, + { url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" }, + { url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" }, + { url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" }, + { url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" }, + { url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" }, + { url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" }, + { url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" }, + { url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" }, + { url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" }, + { url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" }, + { url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" }, + { url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" }, + { url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" }, + { url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" }, + { url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" }, + { url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" }, + { url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" }, + { url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" }, + { url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" }, + { url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" }, + { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" }, + { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" }, + { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" }, +] + +[[package]] +name = "numpy" +version = "2.3.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/d0/19/95b3d357407220ed24c139018d2518fab0a61a948e68286a25f1a4d049ff/numpy-2.3.3.tar.gz", hash = "sha256:ddc7c39727ba62b80dfdbedf400d1c10ddfa8eefbd7ec8dcb118be8b56d31029", size = 20576648, upload-time = "2025-09-09T16:54:12.543Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/45/e80d203ef6b267aa29b22714fb558930b27960a0c5ce3c19c999232bb3eb/numpy-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ffc4f5caba7dfcbe944ed674b7eef683c7e94874046454bb79ed7ee0236f59d", size = 21259253, upload-time = "2025-09-09T15:56:02.094Z" }, + { url = "https://files.pythonhosted.org/packages/52/18/cf2c648fccf339e59302e00e5f2bc87725a3ce1992f30f3f78c9044d7c43/numpy-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7e946c7170858a0295f79a60214424caac2ffdb0063d4d79cb681f9aa0aa569", size = 14450980, upload-time = "2025-09-09T15:56:05.926Z" }, + { url = "https://files.pythonhosted.org/packages/93/fb/9af1082bec870188c42a1c239839915b74a5099c392389ff04215dcee812/numpy-2.3.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:cd4260f64bc794c3390a63bf0728220dd1a68170c169088a1e0dfa2fde1be12f", size = 5379709, upload-time = "2025-09-09T15:56:07.95Z" }, + { url = "https://files.pythonhosted.org/packages/75/0f/bfd7abca52bcbf9a4a65abc83fe18ef01ccdeb37bfb28bbd6ad613447c79/numpy-2.3.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:f0ddb4b96a87b6728df9362135e764eac3cfa674499943ebc44ce96c478ab125", size = 6913923, upload-time = "2025-09-09T15:56:09.443Z" }, + { url = "https://files.pythonhosted.org/packages/79/55/d69adad255e87ab7afda1caf93ca997859092afeb697703e2f010f7c2e55/numpy-2.3.3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:afd07d377f478344ec6ca2b8d4ca08ae8bd44706763d1efb56397de606393f48", size = 14589591, upload-time = "2025-09-09T15:56:11.234Z" }, + { url = "https://files.pythonhosted.org/packages/10/a2/010b0e27ddeacab7839957d7a8f00e91206e0c2c47abbb5f35a2630e5387/numpy-2.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bc92a5dedcc53857249ca51ef29f5e5f2f8c513e22cfb90faeb20343b8c6f7a6", size = 16938714, upload-time = "2025-09-09T15:56:14.637Z" }, + { url = "https://files.pythonhosted.org/packages/1c/6b/12ce8ede632c7126eb2762b9e15e18e204b81725b81f35176eac14dc5b82/numpy-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7af05ed4dc19f308e1d9fc759f36f21921eb7bbfc82843eeec6b2a2863a0aefa", size = 16370592, upload-time = "2025-09-09T15:56:17.285Z" }, + { url = "https://files.pythonhosted.org/packages/b4/35/aba8568b2593067bb6a8fe4c52babb23b4c3b9c80e1b49dff03a09925e4a/numpy-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:433bf137e338677cebdd5beac0199ac84712ad9d630b74eceeb759eaa45ddf30", size = 18884474, upload-time = "2025-09-09T15:56:20.943Z" }, + { url = "https://files.pythonhosted.org/packages/45/fa/7f43ba10c77575e8be7b0138d107e4f44ca4a1ef322cd16980ea3e8b8222/numpy-2.3.3-cp311-cp311-win32.whl", hash = "sha256:eb63d443d7b4ffd1e873f8155260d7f58e7e4b095961b01c91062935c2491e57", size = 6599794, upload-time = "2025-09-09T15:56:23.258Z" }, + { url = "https://files.pythonhosted.org/packages/0a/a2/a4f78cb2241fe5664a22a10332f2be886dcdea8784c9f6a01c272da9b426/numpy-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:ec9d249840f6a565f58d8f913bccac2444235025bbb13e9a4681783572ee3caa", size = 13088104, upload-time = "2025-09-09T15:56:25.476Z" }, + { url = "https://files.pythonhosted.org/packages/79/64/e424e975adbd38282ebcd4891661965b78783de893b381cbc4832fb9beb2/numpy-2.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:74c2a948d02f88c11a3c075d9733f1ae67d97c6bdb97f2bb542f980458b257e7", size = 10460772, upload-time = "2025-09-09T15:56:27.679Z" }, + { url = "https://files.pythonhosted.org/packages/51/5d/bb7fc075b762c96329147799e1bcc9176ab07ca6375ea976c475482ad5b3/numpy-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cfdd09f9c84a1a934cde1eec2267f0a43a7cd44b2cca4ff95b7c0d14d144b0bf", size = 20957014, upload-time = "2025-09-09T15:56:29.966Z" }, + { url = "https://files.pythonhosted.org/packages/6b/0e/c6211bb92af26517acd52125a237a92afe9c3124c6a68d3b9f81b62a0568/numpy-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb32e3cf0f762aee47ad1ddc6672988f7f27045b0783c887190545baba73aa25", size = 14185220, upload-time = "2025-09-09T15:56:32.175Z" }, + { url = "https://files.pythonhosted.org/packages/22/f2/07bb754eb2ede9073f4054f7c0286b0d9d2e23982e090a80d478b26d35ca/numpy-2.3.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:396b254daeb0a57b1fe0ecb5e3cff6fa79a380fa97c8f7781a6d08cd429418fe", size = 5113918, upload-time = "2025-09-09T15:56:34.175Z" }, + { url = "https://files.pythonhosted.org/packages/81/0a/afa51697e9fb74642f231ea36aca80fa17c8fb89f7a82abd5174023c3960/numpy-2.3.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:067e3d7159a5d8f8a0b46ee11148fc35ca9b21f61e3c49fbd0a027450e65a33b", size = 6647922, upload-time = "2025-09-09T15:56:36.149Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f5/122d9cdb3f51c520d150fef6e87df9279e33d19a9611a87c0d2cf78a89f4/numpy-2.3.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c02d0629d25d426585fb2e45a66154081b9fa677bc92a881ff1d216bc9919a8", size = 14281991, upload-time = "2025-09-09T15:56:40.548Z" }, + { url = "https://files.pythonhosted.org/packages/51/64/7de3c91e821a2debf77c92962ea3fe6ac2bc45d0778c1cbe15d4fce2fd94/numpy-2.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9192da52b9745f7f0766531dcfa978b7763916f158bb63bdb8a1eca0068ab20", size = 16641643, upload-time = "2025-09-09T15:56:43.343Z" }, + { url = "https://files.pythonhosted.org/packages/30/e4/961a5fa681502cd0d68907818b69f67542695b74e3ceaa513918103b7e80/numpy-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cd7de500a5b66319db419dc3c345244404a164beae0d0937283b907d8152e6ea", size = 16056787, upload-time = "2025-09-09T15:56:46.141Z" }, + { url = "https://files.pythonhosted.org/packages/99/26/92c912b966e47fbbdf2ad556cb17e3a3088e2e1292b9833be1dfa5361a1a/numpy-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:93d4962d8f82af58f0b2eb85daaf1b3ca23fe0a85d0be8f1f2b7bb46034e56d7", size = 18579598, upload-time = "2025-09-09T15:56:49.844Z" }, + { url = "https://files.pythonhosted.org/packages/17/b6/fc8f82cb3520768718834f310c37d96380d9dc61bfdaf05fe5c0b7653e01/numpy-2.3.3-cp312-cp312-win32.whl", hash = "sha256:5534ed6b92f9b7dca6c0a19d6df12d41c68b991cef051d108f6dbff3babc4ebf", size = 6320800, upload-time = "2025-09-09T15:56:52.499Z" }, + { url = "https://files.pythonhosted.org/packages/32/ee/de999f2625b80d043d6d2d628c07d0d5555a677a3cf78fdf868d409b8766/numpy-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:497d7cad08e7092dba36e3d296fe4c97708c93daf26643a1ae4b03f6294d30eb", size = 12786615, upload-time = "2025-09-09T15:56:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/49/6e/b479032f8a43559c383acb20816644f5f91c88f633d9271ee84f3b3a996c/numpy-2.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:ca0309a18d4dfea6fc6262a66d06c26cfe4640c3926ceec90e57791a82b6eee5", size = 10195936, upload-time = "2025-09-09T15:56:56.541Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b9/984c2b1ee61a8b803bf63582b4ac4242cf76e2dbd663efeafcb620cc0ccb/numpy-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f5415fb78995644253370985342cd03572ef8620b934da27d77377a2285955bf", size = 20949588, upload-time = "2025-09-09T15:56:59.087Z" }, + { url = "https://files.pythonhosted.org/packages/a6/e4/07970e3bed0b1384d22af1e9912527ecbeb47d3b26e9b6a3bced068b3bea/numpy-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d00de139a3324e26ed5b95870ce63be7ec7352171bc69a4cf1f157a48e3eb6b7", size = 14177802, upload-time = "2025-09-09T15:57:01.73Z" }, + { url = "https://files.pythonhosted.org/packages/35/c7/477a83887f9de61f1203bad89cf208b7c19cc9fef0cebef65d5a1a0619f2/numpy-2.3.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9dc13c6a5829610cc07422bc74d3ac083bd8323f14e2827d992f9e52e22cd6a6", size = 5106537, upload-time = "2025-09-09T15:57:03.765Z" }, + { url = "https://files.pythonhosted.org/packages/52/47/93b953bd5866a6f6986344d045a207d3f1cfbad99db29f534ea9cee5108c/numpy-2.3.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d79715d95f1894771eb4e60fb23f065663b2298f7d22945d66877aadf33d00c7", size = 6640743, upload-time = "2025-09-09T15:57:07.921Z" }, + { url = "https://files.pythonhosted.org/packages/23/83/377f84aaeb800b64c0ef4de58b08769e782edcefa4fea712910b6f0afd3c/numpy-2.3.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:952cfd0748514ea7c3afc729a0fc639e61655ce4c55ab9acfab14bda4f402b4c", size = 14278881, upload-time = "2025-09-09T15:57:11.349Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a5/bf3db6e66c4b160d6ea10b534c381a1955dfab34cb1017ea93aa33c70ed3/numpy-2.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b83648633d46f77039c29078751f80da65aa64d5622a3cd62aaef9d835b6c93", size = 16636301, upload-time = "2025-09-09T15:57:14.245Z" }, + { url = "https://files.pythonhosted.org/packages/a2/59/1287924242eb4fa3f9b3a2c30400f2e17eb2707020d1c5e3086fe7330717/numpy-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b001bae8cea1c7dfdb2ae2b017ed0a6f2102d7a70059df1e338e307a4c78a8ae", size = 16053645, upload-time = "2025-09-09T15:57:16.534Z" }, + { url = "https://files.pythonhosted.org/packages/e6/93/b3d47ed882027c35e94ac2320c37e452a549f582a5e801f2d34b56973c97/numpy-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8e9aced64054739037d42fb84c54dd38b81ee238816c948c8f3ed134665dcd86", size = 18578179, upload-time = "2025-09-09T15:57:18.883Z" }, + { url = "https://files.pythonhosted.org/packages/20/d9/487a2bccbf7cc9d4bfc5f0f197761a5ef27ba870f1e3bbb9afc4bbe3fcc2/numpy-2.3.3-cp313-cp313-win32.whl", hash = "sha256:9591e1221db3f37751e6442850429b3aabf7026d3b05542d102944ca7f00c8a8", size = 6312250, upload-time = "2025-09-09T15:57:21.296Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b5/263ebbbbcede85028f30047eab3d58028d7ebe389d6493fc95ae66c636ab/numpy-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f0dadeb302887f07431910f67a14d57209ed91130be0adea2f9793f1a4f817cf", size = 12783269, upload-time = "2025-09-09T15:57:23.034Z" }, + { url = "https://files.pythonhosted.org/packages/fa/75/67b8ca554bbeaaeb3fac2e8bce46967a5a06544c9108ec0cf5cece559b6c/numpy-2.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:3c7cf302ac6e0b76a64c4aecf1a09e51abd9b01fc7feee80f6c43e3ab1b1dbc5", size = 10195314, upload-time = "2025-09-09T15:57:25.045Z" }, + { url = "https://files.pythonhosted.org/packages/11/d0/0d1ddec56b162042ddfafeeb293bac672de9b0cfd688383590090963720a/numpy-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:eda59e44957d272846bb407aad19f89dc6f58fecf3504bd144f4c5cf81a7eacc", size = 21048025, upload-time = "2025-09-09T15:57:27.257Z" }, + { url = "https://files.pythonhosted.org/packages/36/9e/1996ca6b6d00415b6acbdd3c42f7f03ea256e2c3f158f80bd7436a8a19f3/numpy-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:823d04112bc85ef5c4fda73ba24e6096c8f869931405a80aa8b0e604510a26bc", size = 14301053, upload-time = "2025-09-09T15:57:30.077Z" }, + { url = "https://files.pythonhosted.org/packages/05/24/43da09aa764c68694b76e84b3d3f0c44cb7c18cdc1ba80e48b0ac1d2cd39/numpy-2.3.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:40051003e03db4041aa325da2a0971ba41cf65714e65d296397cc0e32de6018b", size = 5229444, upload-time = "2025-09-09T15:57:32.733Z" }, + { url = "https://files.pythonhosted.org/packages/bc/14/50ffb0f22f7218ef8af28dd089f79f68289a7a05a208db9a2c5dcbe123c1/numpy-2.3.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ee9086235dd6ab7ae75aba5662f582a81ced49f0f1c6de4260a78d8f2d91a19", size = 6738039, upload-time = "2025-09-09T15:57:34.328Z" }, + { url = "https://files.pythonhosted.org/packages/55/52/af46ac0795e09657d45a7f4db961917314377edecf66db0e39fa7ab5c3d3/numpy-2.3.3-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94fcaa68757c3e2e668ddadeaa86ab05499a70725811e582b6a9858dd472fb30", size = 14352314, upload-time = "2025-09-09T15:57:36.255Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b1/dc226b4c90eb9f07a3fff95c2f0db3268e2e54e5cce97c4ac91518aee71b/numpy-2.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da1a74b90e7483d6ce5244053399a614b1d6b7bc30a60d2f570e5071f8959d3e", size = 16701722, upload-time = "2025-09-09T15:57:38.622Z" }, + { url = "https://files.pythonhosted.org/packages/9d/9d/9d8d358f2eb5eced14dba99f110d83b5cd9a4460895230f3b396ad19a323/numpy-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2990adf06d1ecee3b3dcbb4977dfab6e9f09807598d647f04d385d29e7a3c3d3", size = 16132755, upload-time = "2025-09-09T15:57:41.16Z" }, + { url = "https://files.pythonhosted.org/packages/b6/27/b3922660c45513f9377b3fb42240bec63f203c71416093476ec9aa0719dc/numpy-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ed635ff692483b8e3f0fcaa8e7eb8a75ee71aa6d975388224f70821421800cea", size = 18651560, upload-time = "2025-09-09T15:57:43.459Z" }, + { url = "https://files.pythonhosted.org/packages/5b/8e/3ab61a730bdbbc201bb245a71102aa609f0008b9ed15255500a99cd7f780/numpy-2.3.3-cp313-cp313t-win32.whl", hash = "sha256:a333b4ed33d8dc2b373cc955ca57babc00cd6f9009991d9edc5ddbc1bac36bcd", size = 6442776, upload-time = "2025-09-09T15:57:45.793Z" }, + { url = "https://files.pythonhosted.org/packages/1c/3a/e22b766b11f6030dc2decdeff5c2fb1610768055603f9f3be88b6d192fb2/numpy-2.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4384a169c4d8f97195980815d6fcad04933a7e1ab3b530921c3fef7a1c63426d", size = 12927281, upload-time = "2025-09-09T15:57:47.492Z" }, + { url = "https://files.pythonhosted.org/packages/7b/42/c2e2bc48c5e9b2a83423f99733950fbefd86f165b468a3d85d52b30bf782/numpy-2.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:75370986cc0bc66f4ce5110ad35aae6d182cc4ce6433c40ad151f53690130bf1", size = 10265275, upload-time = "2025-09-09T15:57:49.647Z" }, + { url = "https://files.pythonhosted.org/packages/6b/01/342ad585ad82419b99bcf7cebe99e61da6bedb89e213c5fd71acc467faee/numpy-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cd052f1fa6a78dee696b58a914b7229ecfa41f0a6d96dc663c1220a55e137593", size = 20951527, upload-time = "2025-09-09T15:57:52.006Z" }, + { url = "https://files.pythonhosted.org/packages/ef/d8/204e0d73fc1b7a9ee80ab1fe1983dd33a4d64a4e30a05364b0208e9a241a/numpy-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:414a97499480067d305fcac9716c29cf4d0d76db6ebf0bf3cbce666677f12652", size = 14186159, upload-time = "2025-09-09T15:57:54.407Z" }, + { url = "https://files.pythonhosted.org/packages/22/af/f11c916d08f3a18fb8ba81ab72b5b74a6e42ead4c2846d270eb19845bf74/numpy-2.3.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:50a5fe69f135f88a2be9b6ca0481a68a136f6febe1916e4920e12f1a34e708a7", size = 5114624, upload-time = "2025-09-09T15:57:56.5Z" }, + { url = "https://files.pythonhosted.org/packages/fb/11/0ed919c8381ac9d2ffacd63fd1f0c34d27e99cab650f0eb6f110e6ae4858/numpy-2.3.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:b912f2ed2b67a129e6a601e9d93d4fa37bef67e54cac442a2f588a54afe5c67a", size = 6642627, upload-time = "2025-09-09T15:57:58.206Z" }, + { url = "https://files.pythonhosted.org/packages/ee/83/deb5f77cb0f7ba6cb52b91ed388b47f8f3c2e9930d4665c600408d9b90b9/numpy-2.3.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e318ee0596d76d4cb3d78535dc005fa60e5ea348cd131a51e99d0bdbe0b54fe", size = 14296926, upload-time = "2025-09-09T15:58:00.035Z" }, + { url = "https://files.pythonhosted.org/packages/77/cc/70e59dcb84f2b005d4f306310ff0a892518cc0c8000a33d0e6faf7ca8d80/numpy-2.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce020080e4a52426202bdb6f7691c65bb55e49f261f31a8f506c9f6bc7450421", size = 16638958, upload-time = "2025-09-09T15:58:02.738Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5a/b2ab6c18b4257e099587d5b7f903317bd7115333ad8d4ec4874278eafa61/numpy-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e6687dc183aa55dae4a705b35f9c0f8cb178bcaa2f029b241ac5356221d5c021", size = 16071920, upload-time = "2025-09-09T15:58:05.029Z" }, + { url = "https://files.pythonhosted.org/packages/b8/f1/8b3fdc44324a259298520dd82147ff648979bed085feeacc1250ef1656c0/numpy-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d8f3b1080782469fdc1718c4ed1d22549b5fb12af0d57d35e992158a772a37cf", size = 18577076, upload-time = "2025-09-09T15:58:07.745Z" }, + { url = "https://files.pythonhosted.org/packages/f0/a1/b87a284fb15a42e9274e7fcea0dad259d12ddbf07c1595b26883151ca3b4/numpy-2.3.3-cp314-cp314-win32.whl", hash = "sha256:cb248499b0bc3be66ebd6578b83e5acacf1d6cb2a77f2248ce0e40fbec5a76d0", size = 6366952, upload-time = "2025-09-09T15:58:10.096Z" }, + { url = "https://files.pythonhosted.org/packages/70/5f/1816f4d08f3b8f66576d8433a66f8fa35a5acfb3bbd0bf6c31183b003f3d/numpy-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:691808c2b26b0f002a032c73255d0bd89751425f379f7bcd22d140db593a96e8", size = 12919322, upload-time = "2025-09-09T15:58:12.138Z" }, + { url = "https://files.pythonhosted.org/packages/8c/de/072420342e46a8ea41c324a555fa90fcc11637583fb8df722936aed1736d/numpy-2.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:9ad12e976ca7b10f1774b03615a2a4bab8addce37ecc77394d8e986927dc0dfe", size = 10478630, upload-time = "2025-09-09T15:58:14.64Z" }, + { url = "https://files.pythonhosted.org/packages/d5/df/ee2f1c0a9de7347f14da5dd3cd3c3b034d1b8607ccb6883d7dd5c035d631/numpy-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9cc48e09feb11e1db00b320e9d30a4151f7369afb96bd0e48d942d09da3a0d00", size = 21047987, upload-time = "2025-09-09T15:58:16.889Z" }, + { url = "https://files.pythonhosted.org/packages/d6/92/9453bdc5a4e9e69cf4358463f25e8260e2ffc126d52e10038b9077815989/numpy-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:901bf6123879b7f251d3631967fd574690734236075082078e0571977c6a8e6a", size = 14301076, upload-time = "2025-09-09T15:58:20.343Z" }, + { url = "https://files.pythonhosted.org/packages/13/77/1447b9eb500f028bb44253105bd67534af60499588a5149a94f18f2ca917/numpy-2.3.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:7f025652034199c301049296b59fa7d52c7e625017cae4c75d8662e377bf487d", size = 5229491, upload-time = "2025-09-09T15:58:22.481Z" }, + { url = "https://files.pythonhosted.org/packages/3d/f9/d72221b6ca205f9736cb4b2ce3b002f6e45cd67cd6a6d1c8af11a2f0b649/numpy-2.3.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:533ca5f6d325c80b6007d4d7fb1984c303553534191024ec6a524a4c92a5935a", size = 6737913, upload-time = "2025-09-09T15:58:24.569Z" }, + { url = "https://files.pythonhosted.org/packages/3c/5f/d12834711962ad9c46af72f79bb31e73e416ee49d17f4c797f72c96b6ca5/numpy-2.3.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0edd58682a399824633b66885d699d7de982800053acf20be1eaa46d92009c54", size = 14352811, upload-time = "2025-09-09T15:58:26.416Z" }, + { url = "https://files.pythonhosted.org/packages/a1/0d/fdbec6629d97fd1bebed56cd742884e4eead593611bbe1abc3eb40d304b2/numpy-2.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:367ad5d8fbec5d9296d18478804a530f1191e24ab4d75ab408346ae88045d25e", size = 16702689, upload-time = "2025-09-09T15:58:28.831Z" }, + { url = "https://files.pythonhosted.org/packages/9b/09/0a35196dc5575adde1eb97ddfbc3e1687a814f905377621d18ca9bc2b7dd/numpy-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8f6ac61a217437946a1fa48d24c47c91a0c4f725237871117dea264982128097", size = 16133855, upload-time = "2025-09-09T15:58:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/7a/ca/c9de3ea397d576f1b6753eaa906d4cdef1bf97589a6d9825a349b4729cc2/numpy-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:179a42101b845a816d464b6fe9a845dfaf308fdfc7925387195570789bb2c970", size = 18652520, upload-time = "2025-09-09T15:58:33.762Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c2/e5ed830e08cd0196351db55db82f65bc0ab05da6ef2b72a836dcf1936d2f/numpy-2.3.3-cp314-cp314t-win32.whl", hash = "sha256:1250c5d3d2562ec4174bce2e3a1523041595f9b651065e4a4473f5f48a6bc8a5", size = 6515371, upload-time = "2025-09-09T15:58:36.04Z" }, + { url = "https://files.pythonhosted.org/packages/47/c7/b0f6b5b67f6788a0725f744496badbb604d226bf233ba716683ebb47b570/numpy-2.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b37a0b2e5935409daebe82c1e42274d30d9dd355852529eab91dab8dcca7419f", size = 13112576, upload-time = "2025-09-09T15:58:37.927Z" }, + { url = "https://files.pythonhosted.org/packages/06/b9/33bba5ff6fb679aa0b1f8a07e853f002a6b04b9394db3069a1270a7784ca/numpy-2.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:78c9f6560dc7e6b3990e32df7ea1a50bbd0e2a111e05209963f5ddcab7073b0b", size = 10545953, upload-time = "2025-09-09T15:58:40.576Z" }, + { url = "https://files.pythonhosted.org/packages/b8/f2/7e0a37cfced2644c9563c529f29fa28acbd0960dde32ece683aafa6f4949/numpy-2.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1e02c7159791cd481e1e6d5ddd766b62a4d5acf8df4d4d1afe35ee9c5c33a41e", size = 21131019, upload-time = "2025-09-09T15:58:42.838Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/3291f505297ed63831135a6cc0f474da0c868a1f31b0dd9a9f03a7a0d2ed/numpy-2.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:dca2d0fc80b3893ae72197b39f69d55a3cd8b17ea1b50aa4c62de82419936150", size = 14376288, upload-time = "2025-09-09T15:58:45.425Z" }, + { url = "https://files.pythonhosted.org/packages/bf/4b/ae02e985bdeee73d7b5abdefeb98aef1207e96d4c0621ee0cf228ddfac3c/numpy-2.3.3-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:99683cbe0658f8271b333a1b1b4bb3173750ad59c0c61f5bbdc5b318918fffe3", size = 5305425, upload-time = "2025-09-09T15:58:48.6Z" }, + { url = "https://files.pythonhosted.org/packages/8b/eb/9df215d6d7250db32007941500dc51c48190be25f2401d5b2b564e467247/numpy-2.3.3-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:d9d537a39cc9de668e5cd0e25affb17aec17b577c6b3ae8a3d866b479fbe88d0", size = 6819053, upload-time = "2025-09-09T15:58:50.401Z" }, + { url = "https://files.pythonhosted.org/packages/57/62/208293d7d6b2a8998a4a1f23ac758648c3c32182d4ce4346062018362e29/numpy-2.3.3-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8596ba2f8af5f93b01d97563832686d20206d303024777f6dfc2e7c7c3f1850e", size = 14420354, upload-time = "2025-09-09T15:58:52.704Z" }, + { url = "https://files.pythonhosted.org/packages/ed/0c/8e86e0ff7072e14a71b4c6af63175e40d1e7e933ce9b9e9f765a95b4e0c3/numpy-2.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1ec5615b05369925bd1125f27df33f3b6c8bc10d788d5999ecd8769a1fa04db", size = 16760413, upload-time = "2025-09-09T15:58:55.027Z" }, + { url = "https://files.pythonhosted.org/packages/af/11/0cc63f9f321ccf63886ac203336777140011fb669e739da36d8db3c53b98/numpy-2.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2e267c7da5bf7309670523896df97f93f6e469fb931161f483cd6882b3b1a5dc", size = 12971844, upload-time = "2025-09-09T15:58:57.359Z" }, +] + +[[package]] +name = "nvidia-cublas-cu12" +version = "12.6.4.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/eb/ff4b8c503fa1f1796679dce648854d58751982426e4e4b37d6fce49d259c/nvidia_cublas_cu12-12.6.4.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:08ed2686e9875d01b58e3cb379c6896df8e76c75e0d4a7f7dace3d7b6d9ef8eb", size = 393138322, upload-time = "2024-11-20T17:40:25.65Z" }, +] + +[[package]] +name = "nvidia-cuda-cupti-cu12" +version = "12.6.80" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/60/7b6497946d74bcf1de852a21824d63baad12cd417db4195fc1bfe59db953/nvidia_cuda_cupti_cu12-12.6.80-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6768bad6cab4f19e8292125e5f1ac8aa7d1718704012a0e3272a6f61c4bce132", size = 8917980, upload-time = "2024-11-20T17:36:04.019Z" }, + { url = "https://files.pythonhosted.org/packages/a5/24/120ee57b218d9952c379d1e026c4479c9ece9997a4fb46303611ee48f038/nvidia_cuda_cupti_cu12-12.6.80-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a3eff6cdfcc6a4c35db968a06fcadb061cbc7d6dde548609a941ff8701b98b73", size = 8917972, upload-time = "2024-10-01T16:58:06.036Z" }, +] + +[[package]] +name = "nvidia-cuda-nvrtc-cu12" +version = "12.6.77" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/2e/46030320b5a80661e88039f59060d1790298b4718944a65a7f2aeda3d9e9/nvidia_cuda_nvrtc_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:35b0cc6ee3a9636d5409133e79273ce1f3fd087abb0532d2d2e8fff1fe9efc53", size = 23650380, upload-time = "2024-10-01T17:00:14.643Z" }, +] + +[[package]] +name = "nvidia-cuda-runtime-cu12" +version = "12.6.77" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/23/e717c5ac26d26cf39a27fbc076240fad2e3b817e5889d671b67f4f9f49c5/nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ba3b56a4f896141e25e19ab287cd71e52a6a0f4b29d0d31609f60e3b4d5219b7", size = 897690, upload-time = "2024-11-20T17:35:30.697Z" }, + { url = "https://files.pythonhosted.org/packages/f0/62/65c05e161eeddbafeca24dc461f47de550d9fa8a7e04eb213e32b55cfd99/nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a84d15d5e1da416dd4774cb42edf5e954a3e60cc945698dc1d5be02321c44dc8", size = 897678, upload-time = "2024-10-01T16:57:33.821Z" }, +] + +[[package]] +name = "nvidia-cudnn-cu12" +version = "9.5.1.17" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cublas-cu12" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/78/4535c9c7f859a64781e43c969a3a7e84c54634e319a996d43ef32ce46f83/nvidia_cudnn_cu12-9.5.1.17-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:30ac3869f6db17d170e0e556dd6cc5eee02647abc31ca856634d5a40f82c15b2", size = 570988386, upload-time = "2024-10-25T19:54:26.39Z" }, +] + +[[package]] +name = "nvidia-cufft-cu12" +version = "11.3.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-nvjitlink-cu12" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/16/73727675941ab8e6ffd86ca3a4b7b47065edcca7a997920b831f8147c99d/nvidia_cufft_cu12-11.3.0.4-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ccba62eb9cef5559abd5e0d54ceed2d9934030f51163df018532142a8ec533e5", size = 200221632, upload-time = "2024-11-20T17:41:32.357Z" }, + { url = "https://files.pythonhosted.org/packages/60/de/99ec247a07ea40c969d904fc14f3a356b3e2a704121675b75c366b694ee1/nvidia_cufft_cu12-11.3.0.4-py3-none-manylinux2014_x86_64.whl", hash = "sha256:768160ac89f6f7b459bee747e8d175dbf53619cfe74b2a5636264163138013ca", size = 200221622, upload-time = "2024-10-01T17:03:58.79Z" }, +] + +[[package]] +name = "nvidia-cufile-cu12" +version = "1.11.1.6" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/66/cc9876340ac68ae71b15c743ddb13f8b30d5244af344ec8322b449e35426/nvidia_cufile_cu12-1.11.1.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc23469d1c7e52ce6c1d55253273d32c565dd22068647f3aa59b3c6b005bf159", size = 1142103, upload-time = "2024-11-20T17:42:11.83Z" }, +] + +[[package]] +name = "nvidia-curand-cu12" +version = "10.3.7.77" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/1b/44a01c4e70933637c93e6e1a8063d1e998b50213a6b65ac5a9169c47e98e/nvidia_curand_cu12-10.3.7.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a42cd1344297f70b9e39a1e4f467a4e1c10f1da54ff7a85c12197f6c652c8bdf", size = 56279010, upload-time = "2024-11-20T17:42:50.958Z" }, + { url = "https://files.pythonhosted.org/packages/4a/aa/2c7ff0b5ee02eaef890c0ce7d4f74bc30901871c5e45dee1ae6d0083cd80/nvidia_curand_cu12-10.3.7.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:99f1a32f1ac2bd134897fc7a203f779303261268a65762a623bf30cc9fe79117", size = 56279000, upload-time = "2024-10-01T17:04:45.274Z" }, +] + +[[package]] +name = "nvidia-cusolver-cu12" +version = "11.7.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-cublas-cu12" }, + { name = "nvidia-cusparse-cu12" }, + { name = "nvidia-nvjitlink-cu12" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/6e/c2cf12c9ff8b872e92b4a5740701e51ff17689c4d726fca91875b07f655d/nvidia_cusolver_cu12-11.7.1.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e9e49843a7707e42022babb9bcfa33c29857a93b88020c4e4434656a655b698c", size = 158229790, upload-time = "2024-11-20T17:43:43.211Z" }, + { url = "https://files.pythonhosted.org/packages/9f/81/baba53585da791d043c10084cf9553e074548408e04ae884cfe9193bd484/nvidia_cusolver_cu12-11.7.1.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6cf28f17f64107a0c4d7802be5ff5537b2130bfc112f25d5a30df227058ca0e6", size = 158229780, upload-time = "2024-10-01T17:05:39.875Z" }, +] + +[[package]] +name = "nvidia-cusparse-cu12" +version = "12.5.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nvidia-nvjitlink-cu12" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/1e/b8b7c2f4099a37b96af5c9bb158632ea9e5d9d27d7391d7eb8fc45236674/nvidia_cusparse_cu12-12.5.4.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7556d9eca156e18184b94947ade0fba5bb47d69cec46bf8660fd2c71a4b48b73", size = 216561367, upload-time = "2024-11-20T17:44:54.824Z" }, + { url = "https://files.pythonhosted.org/packages/43/ac/64c4316ba163e8217a99680c7605f779accffc6a4bcd0c778c12948d3707/nvidia_cusparse_cu12-12.5.4.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:23749a6571191a215cb74d1cdbff4a86e7b19f1200c071b3fcf844a5bea23a2f", size = 216561357, upload-time = "2024-10-01T17:06:29.861Z" }, +] + +[[package]] +name = "nvidia-cusparselt-cu12" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/9a/72ef35b399b0e183bc2e8f6f558036922d453c4d8237dab26c666a04244b/nvidia_cusparselt_cu12-0.6.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:e5c8a26c36445dd2e6812f1177978a24e2d37cacce7e090f297a688d1ec44f46", size = 156785796, upload-time = "2024-10-15T21:29:17.709Z" }, +] + +[[package]] +name = "nvidia-nccl-cu12" +version = "2.26.2" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/ca/f42388aed0fddd64ade7493dbba36e1f534d4e6fdbdd355c6a90030ae028/nvidia_nccl_cu12-2.26.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:694cf3879a206553cc9d7dbda76b13efaf610fdb70a50cba303de1b0d1530ac6", size = 201319755, upload-time = "2025-03-13T00:29:55.296Z" }, +] + +[[package]] +name = "nvidia-nvjitlink-cu12" +version = "12.6.85" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/d7/c5383e47c7e9bf1c99d5bd2a8c935af2b6d705ad831a7ec5c97db4d82f4f/nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl", hash = "sha256:eedc36df9e88b682efe4309aa16b5b4e78c2407eac59e8c10a6a47535164369a", size = 19744971, upload-time = "2024-11-20T17:46:53.366Z" }, +] + +[[package]] +name = "nvidia-nvtx-cu12" +version = "12.6.77" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/9a/fff8376f8e3d084cd1530e1ef7b879bb7d6d265620c95c1b322725c694f4/nvidia_nvtx_cu12-12.6.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b90bed3df379fa79afbd21be8e04a0314336b8ae16768b58f2d34cb1d04cd7d2", size = 89276, upload-time = "2024-11-20T17:38:27.621Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4e/0d0c945463719429b7bd21dece907ad0bde437a2ff12b9b12fee94722ab0/nvidia_nvtx_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6574241a3ec5fdc9334353ab8c479fe75841dbe8f4532a8fc97ce63503330ba1", size = 89265, upload-time = "2024-10-01T17:00:38.172Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pandas" +version = "2.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c", size = 11555763, upload-time = "2025-09-29T23:16:53.287Z" }, + { url = "https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a", size = 10801217, upload-time = "2025-09-29T23:17:04.522Z" }, + { url = "https://files.pythonhosted.org/packages/1d/03/3fc4a529a7710f890a239cc496fc6d50ad4a0995657dccc1d64695adb9f4/pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1", size = 12148791, upload-time = "2025-09-29T23:17:18.444Z" }, + { url = "https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838", size = 12769373, upload-time = "2025-09-29T23:17:35.846Z" }, + { url = "https://files.pythonhosted.org/packages/df/91/82cc5169b6b25440a7fc0ef3a694582418d875c8e3ebf796a6d6470aa578/pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250", size = 13200444, upload-time = "2025-09-29T23:17:49.341Z" }, + { url = "https://files.pythonhosted.org/packages/10/ae/89b3283800ab58f7af2952704078555fa60c807fff764395bb57ea0b0dbd/pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4", size = 13858459, upload-time = "2025-09-29T23:18:03.722Z" }, + { url = "https://files.pythonhosted.org/packages/85/72/530900610650f54a35a19476eca5104f38555afccda1aa11a92ee14cb21d/pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826", size = 11346086, upload-time = "2025-09-29T23:18:18.505Z" }, + { url = "https://files.pythonhosted.org/packages/c1/fa/7ac648108144a095b4fb6aa3de1954689f7af60a14cf25583f4960ecb878/pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523", size = 11578790, upload-time = "2025-09-29T23:18:30.065Z" }, + { url = "https://files.pythonhosted.org/packages/9b/35/74442388c6cf008882d4d4bdfc4109be87e9b8b7ccd097ad1e7f006e2e95/pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45", size = 10833831, upload-time = "2025-09-29T23:38:56.071Z" }, + { url = "https://files.pythonhosted.org/packages/fe/e4/de154cbfeee13383ad58d23017da99390b91d73f8c11856f2095e813201b/pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66", size = 12199267, upload-time = "2025-09-29T23:18:41.627Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c9/63f8d545568d9ab91476b1818b4741f521646cbdd151c6efebf40d6de6f7/pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b", size = 12789281, upload-time = "2025-09-29T23:18:56.834Z" }, + { url = "https://files.pythonhosted.org/packages/f2/00/a5ac8c7a0e67fd1a6059e40aa08fa1c52cc00709077d2300e210c3ce0322/pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791", size = 13240453, upload-time = "2025-09-29T23:19:09.247Z" }, + { url = "https://files.pythonhosted.org/packages/27/4d/5c23a5bc7bd209231618dd9e606ce076272c9bc4f12023a70e03a86b4067/pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151", size = 13890361, upload-time = "2025-09-29T23:19:25.342Z" }, + { url = "https://files.pythonhosted.org/packages/8e/59/712db1d7040520de7a4965df15b774348980e6df45c129b8c64d0dbe74ef/pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c", size = 11348702, upload-time = "2025-09-29T23:19:38.296Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fb/231d89e8637c808b997d172b18e9d4a4bc7bf31296196c260526055d1ea0/pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53", size = 11597846, upload-time = "2025-09-29T23:19:48.856Z" }, + { url = "https://files.pythonhosted.org/packages/5c/bd/bf8064d9cfa214294356c2d6702b716d3cf3bb24be59287a6a21e24cae6b/pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35", size = 10729618, upload-time = "2025-09-29T23:39:08.659Z" }, + { url = "https://files.pythonhosted.org/packages/57/56/cf2dbe1a3f5271370669475ead12ce77c61726ffd19a35546e31aa8edf4e/pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908", size = 11737212, upload-time = "2025-09-29T23:19:59.765Z" }, + { url = "https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89", size = 12362693, upload-time = "2025-09-29T23:20:14.098Z" }, + { url = "https://files.pythonhosted.org/packages/a6/de/8b1895b107277d52f2b42d3a6806e69cfef0d5cf1d0ba343470b9d8e0a04/pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", size = 12771002, upload-time = "2025-09-29T23:20:26.76Z" }, + { url = "https://files.pythonhosted.org/packages/87/21/84072af3187a677c5893b170ba2c8fbe450a6ff911234916da889b698220/pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", size = 13450971, upload-time = "2025-09-29T23:20:41.344Z" }, + { url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" }, + { url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" }, + { url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" }, + { url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" }, + { url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" }, + { url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" }, + { url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" }, + { url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" }, + { url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" }, + { url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" }, + { url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" }, + { url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" }, + { url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" }, + { url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" }, + { url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" }, + { url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" }, + { url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" }, + { url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" }, + { url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" }, + { url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" }, + { url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" }, + { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, +] + +[[package]] +name = "pillow" +version = "12.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/cace85a1b0c9775a9f8f5d5423c8261c858760e2466c79b2dd184638b056/pillow-12.0.0.tar.gz", hash = "sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353", size = 47008828, upload-time = "2025-10-15T18:24:14.008Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/08/26e68b6b5da219c2a2cb7b563af008b53bb8e6b6fcb3fa40715fcdb2523a/pillow-12.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:3adfb466bbc544b926d50fe8f4a4e6abd8c6bffd28a26177594e6e9b2b76572b", size = 5289809, upload-time = "2025-10-15T18:21:27.791Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e9/4e58fb097fb74c7b4758a680aacd558810a417d1edaa7000142976ef9d2f/pillow-12.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1ac11e8ea4f611c3c0147424eae514028b5e9077dd99ab91e1bd7bc33ff145e1", size = 4650606, upload-time = "2025-10-15T18:21:29.823Z" }, + { url = "https://files.pythonhosted.org/packages/4b/e0/1fa492aa9f77b3bc6d471c468e62bfea1823056bf7e5e4f1914d7ab2565e/pillow-12.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d49e2314c373f4c2b39446fb1a45ed333c850e09d0c59ac79b72eb3b95397363", size = 6221023, upload-time = "2025-10-15T18:21:31.415Z" }, + { url = "https://files.pythonhosted.org/packages/c1/09/4de7cd03e33734ccd0c876f0251401f1314e819cbfd89a0fcb6e77927cc6/pillow-12.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c7b2a63fd6d5246349f3d3f37b14430d73ee7e8173154461785e43036ffa96ca", size = 8024937, upload-time = "2025-10-15T18:21:33.453Z" }, + { url = "https://files.pythonhosted.org/packages/2e/69/0688e7c1390666592876d9d474f5e135abb4acb39dcb583c4dc5490f1aff/pillow-12.0.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d64317d2587c70324b79861babb9c09f71fbb780bad212018874b2c013d8600e", size = 6334139, upload-time = "2025-10-15T18:21:35.395Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1c/880921e98f525b9b44ce747ad1ea8f73fd7e992bafe3ca5e5644bf433dea/pillow-12.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d77153e14b709fd8b8af6f66a3afbb9ed6e9fc5ccf0b6b7e1ced7b036a228782", size = 7026074, upload-time = "2025-10-15T18:21:37.219Z" }, + { url = "https://files.pythonhosted.org/packages/28/03/96f718331b19b355610ef4ebdbbde3557c726513030665071fd025745671/pillow-12.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:32ed80ea8a90ee3e6fa08c21e2e091bba6eda8eccc83dbc34c95169507a91f10", size = 6448852, upload-time = "2025-10-15T18:21:39.168Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a0/6a193b3f0cc9437b122978d2c5cbce59510ccf9a5b48825096ed7472da2f/pillow-12.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c828a1ae702fc712978bda0320ba1b9893d99be0badf2647f693cc01cf0f04fa", size = 7117058, upload-time = "2025-10-15T18:21:40.997Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c4/043192375eaa4463254e8e61f0e2ec9a846b983929a8d0a7122e0a6d6fff/pillow-12.0.0-cp310-cp310-win32.whl", hash = "sha256:bd87e140e45399c818fac4247880b9ce719e4783d767e030a883a970be632275", size = 6295431, upload-time = "2025-10-15T18:21:42.518Z" }, + { url = "https://files.pythonhosted.org/packages/92/c6/c2f2fc7e56301c21827e689bb8b0b465f1b52878b57471a070678c0c33cd/pillow-12.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:455247ac8a4cfb7b9bc45b7e432d10421aea9fc2e74d285ba4072688a74c2e9d", size = 7000412, upload-time = "2025-10-15T18:21:44.404Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d2/5f675067ba82da7a1c238a73b32e3fd78d67f9d9f80fbadd33a40b9c0481/pillow-12.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:6ace95230bfb7cd79ef66caa064bbe2f2a1e63d93471c3a2e1f1348d9f22d6b7", size = 2435903, upload-time = "2025-10-15T18:21:46.29Z" }, + { url = "https://files.pythonhosted.org/packages/0e/5a/a2f6773b64edb921a756eb0729068acad9fc5208a53f4a349396e9436721/pillow-12.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0fd00cac9c03256c8b2ff58f162ebcd2587ad3e1f2e397eab718c47e24d231cc", size = 5289798, upload-time = "2025-10-15T18:21:47.763Z" }, + { url = "https://files.pythonhosted.org/packages/2e/05/069b1f8a2e4b5a37493da6c5868531c3f77b85e716ad7a590ef87d58730d/pillow-12.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3475b96f5908b3b16c47533daaa87380c491357d197564e0ba34ae75c0f3257", size = 4650589, upload-time = "2025-10-15T18:21:49.515Z" }, + { url = "https://files.pythonhosted.org/packages/61/e3/2c820d6e9a36432503ead175ae294f96861b07600a7156154a086ba7111a/pillow-12.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:110486b79f2d112cf6add83b28b627e369219388f64ef2f960fef9ebaf54c642", size = 6230472, upload-time = "2025-10-15T18:21:51.052Z" }, + { url = "https://files.pythonhosted.org/packages/4f/89/63427f51c64209c5e23d4d52071c8d0f21024d3a8a487737caaf614a5795/pillow-12.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5269cc1caeedb67e6f7269a42014f381f45e2e7cd42d834ede3c703a1d915fe3", size = 8033887, upload-time = "2025-10-15T18:21:52.604Z" }, + { url = "https://files.pythonhosted.org/packages/f6/1b/c9711318d4901093c15840f268ad649459cd81984c9ec9887756cca049a5/pillow-12.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa5129de4e174daccbc59d0a3b6d20eaf24417d59851c07ebb37aeb02947987c", size = 6343964, upload-time = "2025-10-15T18:21:54.619Z" }, + { url = "https://files.pythonhosted.org/packages/41/1e/db9470f2d030b4995083044cd8738cdd1bf773106819f6d8ba12597d5352/pillow-12.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bee2a6db3a7242ea309aa7ee8e2780726fed67ff4e5b40169f2c940e7eb09227", size = 7034756, upload-time = "2025-10-15T18:21:56.151Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b0/6177a8bdd5ee4ed87cba2de5a3cc1db55ffbbec6176784ce5bb75aa96798/pillow-12.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:90387104ee8400a7b4598253b4c406f8958f59fcf983a6cea2b50d59f7d63d0b", size = 6458075, upload-time = "2025-10-15T18:21:57.759Z" }, + { url = "https://files.pythonhosted.org/packages/bc/5e/61537aa6fa977922c6a03253a0e727e6e4a72381a80d63ad8eec350684f2/pillow-12.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bc91a56697869546d1b8f0a3ff35224557ae7f881050e99f615e0119bf934b4e", size = 7125955, upload-time = "2025-10-15T18:21:59.372Z" }, + { url = "https://files.pythonhosted.org/packages/1f/3d/d5033539344ee3cbd9a4d69e12e63ca3a44a739eb2d4c8da350a3d38edd7/pillow-12.0.0-cp311-cp311-win32.whl", hash = "sha256:27f95b12453d165099c84f8a8bfdfd46b9e4bda9e0e4b65f0635430027f55739", size = 6298440, upload-time = "2025-10-15T18:22:00.982Z" }, + { url = "https://files.pythonhosted.org/packages/4d/42/aaca386de5cc8bd8a0254516957c1f265e3521c91515b16e286c662854c4/pillow-12.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:b583dc9070312190192631373c6c8ed277254aa6e6084b74bdd0a6d3b221608e", size = 6999256, upload-time = "2025-10-15T18:22:02.617Z" }, + { url = "https://files.pythonhosted.org/packages/ba/f1/9197c9c2d5708b785f631a6dfbfa8eb3fb9672837cb92ae9af812c13b4ed/pillow-12.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:759de84a33be3b178a64c8ba28ad5c135900359e85fb662bc6e403ad4407791d", size = 2436025, upload-time = "2025-10-15T18:22:04.598Z" }, + { url = "https://files.pythonhosted.org/packages/2c/90/4fcce2c22caf044e660a198d740e7fbc14395619e3cb1abad12192c0826c/pillow-12.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:53561a4ddc36facb432fae7a9d8afbfaf94795414f5cdc5fc52f28c1dca90371", size = 5249377, upload-time = "2025-10-15T18:22:05.993Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e0/ed960067543d080691d47d6938ebccbf3976a931c9567ab2fbfab983a5dd/pillow-12.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71db6b4c1653045dacc1585c1b0d184004f0d7e694c7b34ac165ca70c0838082", size = 4650343, upload-time = "2025-10-15T18:22:07.718Z" }, + { url = "https://files.pythonhosted.org/packages/e7/a1/f81fdeddcb99c044bf7d6faa47e12850f13cee0849537a7d27eeab5534d4/pillow-12.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2fa5f0b6716fc88f11380b88b31fe591a06c6315e955c096c35715788b339e3f", size = 6232981, upload-time = "2025-10-15T18:22:09.287Z" }, + { url = "https://files.pythonhosted.org/packages/88/e1/9098d3ce341a8750b55b0e00c03f1630d6178f38ac191c81c97a3b047b44/pillow-12.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:82240051c6ca513c616f7f9da06e871f61bfd7805f566275841af15015b8f98d", size = 8041399, upload-time = "2025-10-15T18:22:10.872Z" }, + { url = "https://files.pythonhosted.org/packages/a7/62/a22e8d3b602ae8cc01446d0c57a54e982737f44b6f2e1e019a925143771d/pillow-12.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55f818bd74fe2f11d4d7cbc65880a843c4075e0ac7226bc1a23261dbea531953", size = 6347740, upload-time = "2025-10-15T18:22:12.769Z" }, + { url = "https://files.pythonhosted.org/packages/4f/87/424511bdcd02c8d7acf9f65caa09f291a519b16bd83c3fb3374b3d4ae951/pillow-12.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b87843e225e74576437fd5b6a4c2205d422754f84a06942cfaf1dc32243e45a8", size = 7040201, upload-time = "2025-10-15T18:22:14.813Z" }, + { url = "https://files.pythonhosted.org/packages/dc/4d/435c8ac688c54d11755aedfdd9f29c9eeddf68d150fe42d1d3dbd2365149/pillow-12.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c607c90ba67533e1b2355b821fef6764d1dd2cbe26b8c1005ae84f7aea25ff79", size = 6462334, upload-time = "2025-10-15T18:22:16.375Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f2/ad34167a8059a59b8ad10bc5c72d4d9b35acc6b7c0877af8ac885b5f2044/pillow-12.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:21f241bdd5080a15bc86d3466a9f6074a9c2c2b314100dd896ac81ee6db2f1ba", size = 7134162, upload-time = "2025-10-15T18:22:17.996Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b1/a7391df6adacf0a5c2cf6ac1cf1fcc1369e7d439d28f637a847f8803beb3/pillow-12.0.0-cp312-cp312-win32.whl", hash = "sha256:dd333073e0cacdc3089525c7df7d39b211bcdf31fc2824e49d01c6b6187b07d0", size = 6298769, upload-time = "2025-10-15T18:22:19.923Z" }, + { url = "https://files.pythonhosted.org/packages/a2/0b/d87733741526541c909bbf159e338dcace4f982daac6e5a8d6be225ca32d/pillow-12.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe611163f6303d1619bbcb653540a4d60f9e55e622d60a3108be0d5b441017a", size = 7001107, upload-time = "2025-10-15T18:22:21.644Z" }, + { url = "https://files.pythonhosted.org/packages/bc/96/aaa61ce33cc98421fb6088af2a03be4157b1e7e0e87087c888e2370a7f45/pillow-12.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:7dfb439562f234f7d57b1ac6bc8fe7f838a4bd49c79230e0f6a1da93e82f1fad", size = 2436012, upload-time = "2025-10-15T18:22:23.621Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/de993bb2d21b33a98d031ecf6a978e4b61da207bef02f7b43093774c480d/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0869154a2d0546545cde61d1789a6524319fc1897d9ee31218eae7a60ccc5643", size = 4045493, upload-time = "2025-10-15T18:22:25.758Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b6/bc8d0c4c9f6f111a783d045310945deb769b806d7574764234ffd50bc5ea/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a7921c5a6d31b3d756ec980f2f47c0cfdbce0fc48c22a39347a895f41f4a6ea4", size = 4120461, upload-time = "2025-10-15T18:22:27.286Z" }, + { url = "https://files.pythonhosted.org/packages/5d/57/d60d343709366a353dc56adb4ee1e7d8a2cc34e3fbc22905f4167cfec119/pillow-12.0.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1ee80a59f6ce048ae13cda1abf7fbd2a34ab9ee7d401c46be3ca685d1999a399", size = 3576912, upload-time = "2025-10-15T18:22:28.751Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a4/a0a31467e3f83b94d37568294b01d22b43ae3c5d85f2811769b9c66389dd/pillow-12.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c50f36a62a22d350c96e49ad02d0da41dbd17ddc2e29750dbdba4323f85eb4a5", size = 5249132, upload-time = "2025-10-15T18:22:30.641Z" }, + { url = "https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b", size = 4650099, upload-time = "2025-10-15T18:22:32.73Z" }, + { url = "https://files.pythonhosted.org/packages/fc/bd/69ed99fd46a8dba7c1887156d3572fe4484e3f031405fcc5a92e31c04035/pillow-12.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bde737cff1a975b70652b62d626f7785e0480918dece11e8fef3c0cf057351c3", size = 6230808, upload-time = "2025-10-15T18:22:34.337Z" }, + { url = "https://files.pythonhosted.org/packages/ea/94/8fad659bcdbf86ed70099cb60ae40be6acca434bbc8c4c0d4ef356d7e0de/pillow-12.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a6597ff2b61d121172f5844b53f21467f7082f5fb385a9a29c01414463f93b07", size = 8037804, upload-time = "2025-10-15T18:22:36.402Z" }, + { url = "https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e", size = 6345553, upload-time = "2025-10-15T18:22:38.066Z" }, + { url = "https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344", size = 7037729, upload-time = "2025-10-15T18:22:39.769Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b6/7e94f4c41d238615674d06ed677c14883103dce1c52e4af16f000338cfd7/pillow-12.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e51b71417049ad6ab14c49608b4a24d8fb3fe605e5dfabfe523b58064dc3d27", size = 6459789, upload-time = "2025-10-15T18:22:41.437Z" }, + { url = "https://files.pythonhosted.org/packages/9c/14/4448bb0b5e0f22dd865290536d20ec8a23b64e2d04280b89139f09a36bb6/pillow-12.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d120c38a42c234dc9a8c5de7ceaaf899cf33561956acb4941653f8bdc657aa79", size = 7130917, upload-time = "2025-10-15T18:22:43.152Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ca/16c6926cc1c015845745d5c16c9358e24282f1e588237a4c36d2b30f182f/pillow-12.0.0-cp313-cp313-win32.whl", hash = "sha256:4cc6b3b2efff105c6a1656cfe59da4fdde2cda9af1c5e0b58529b24525d0a098", size = 6302391, upload-time = "2025-10-15T18:22:44.753Z" }, + { url = "https://files.pythonhosted.org/packages/6d/2a/dd43dcfd6dae9b6a49ee28a8eedb98c7d5ff2de94a5d834565164667b97b/pillow-12.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:4cf7fed4b4580601c4345ceb5d4cbf5a980d030fd5ad07c4d2ec589f95f09905", size = 7007477, upload-time = "2025-10-15T18:22:46.838Z" }, + { url = "https://files.pythonhosted.org/packages/77/f0/72ea067f4b5ae5ead653053212af05ce3705807906ba3f3e8f58ddf617e6/pillow-12.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:9f0b04c6b8584c2c193babcccc908b38ed29524b29dd464bc8801bf10d746a3a", size = 2435918, upload-time = "2025-10-15T18:22:48.399Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5e/9046b423735c21f0487ea6cb5b10f89ea8f8dfbe32576fe052b5ba9d4e5b/pillow-12.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7fa22993bac7b77b78cae22bad1e2a987ddf0d9015c63358032f84a53f23cdc3", size = 5251406, upload-time = "2025-10-15T18:22:49.905Z" }, + { url = "https://files.pythonhosted.org/packages/12/66/982ceebcdb13c97270ef7a56c3969635b4ee7cd45227fa707c94719229c5/pillow-12.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f135c702ac42262573fe9714dfe99c944b4ba307af5eb507abef1667e2cbbced", size = 4653218, upload-time = "2025-10-15T18:22:51.587Z" }, + { url = "https://files.pythonhosted.org/packages/16/b3/81e625524688c31859450119bf12674619429cab3119eec0e30a7a1029cb/pillow-12.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c85de1136429c524e55cfa4e033b4a7940ac5c8ee4d9401cc2d1bf48154bbc7b", size = 6266564, upload-time = "2025-10-15T18:22:53.215Z" }, + { url = "https://files.pythonhosted.org/packages/98/59/dfb38f2a41240d2408096e1a76c671d0a105a4a8471b1871c6902719450c/pillow-12.0.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38df9b4bfd3db902c9c2bd369bcacaf9d935b2fff73709429d95cc41554f7b3d", size = 8069260, upload-time = "2025-10-15T18:22:54.933Z" }, + { url = "https://files.pythonhosted.org/packages/dc/3d/378dbea5cd1874b94c312425ca77b0f47776c78e0df2df751b820c8c1d6c/pillow-12.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d87ef5795da03d742bf49439f9ca4d027cde49c82c5371ba52464aee266699a", size = 6379248, upload-time = "2025-10-15T18:22:56.605Z" }, + { url = "https://files.pythonhosted.org/packages/84/b0/d525ef47d71590f1621510327acec75ae58c721dc071b17d8d652ca494d8/pillow-12.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aff9e4d82d082ff9513bdd6acd4f5bd359f5b2c870907d2b0a9c5e10d40c88fe", size = 7066043, upload-time = "2025-10-15T18:22:58.53Z" }, + { url = "https://files.pythonhosted.org/packages/61/2c/aced60e9cf9d0cde341d54bf7932c9ffc33ddb4a1595798b3a5150c7ec4e/pillow-12.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8d8ca2b210ada074d57fcee40c30446c9562e542fc46aedc19baf758a93532ee", size = 6490915, upload-time = "2025-10-15T18:23:00.582Z" }, + { url = "https://files.pythonhosted.org/packages/ef/26/69dcb9b91f4e59f8f34b2332a4a0a951b44f547c4ed39d3e4dcfcff48f89/pillow-12.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:99a7f72fb6249302aa62245680754862a44179b545ded638cf1fef59befb57ef", size = 7157998, upload-time = "2025-10-15T18:23:02.627Z" }, + { url = "https://files.pythonhosted.org/packages/61/2b/726235842220ca95fa441ddf55dd2382b52ab5b8d9c0596fe6b3f23dafe8/pillow-12.0.0-cp313-cp313t-win32.whl", hash = "sha256:4078242472387600b2ce8d93ade8899c12bf33fa89e55ec89fe126e9d6d5d9e9", size = 6306201, upload-time = "2025-10-15T18:23:04.709Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3d/2afaf4e840b2df71344ababf2f8edd75a705ce500e5dc1e7227808312ae1/pillow-12.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2c54c1a783d6d60595d3514f0efe9b37c8808746a66920315bfd34a938d7994b", size = 7013165, upload-time = "2025-10-15T18:23:06.46Z" }, + { url = "https://files.pythonhosted.org/packages/6f/75/3fa09aa5cf6ed04bee3fa575798ddf1ce0bace8edb47249c798077a81f7f/pillow-12.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:26d9f7d2b604cd23aba3e9faf795787456ac25634d82cd060556998e39c6fa47", size = 2437834, upload-time = "2025-10-15T18:23:08.194Z" }, + { url = "https://files.pythonhosted.org/packages/54/2a/9a8c6ba2c2c07b71bec92cf63e03370ca5e5f5c5b119b742bcc0cde3f9c5/pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:beeae3f27f62308f1ddbcfb0690bf44b10732f2ef43758f169d5e9303165d3f9", size = 4045531, upload-time = "2025-10-15T18:23:10.121Z" }, + { url = "https://files.pythonhosted.org/packages/84/54/836fdbf1bfb3d66a59f0189ff0b9f5f666cee09c6188309300df04ad71fa/pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d4827615da15cd59784ce39d3388275ec093ae3ee8d7f0c089b76fa87af756c2", size = 4120554, upload-time = "2025-10-15T18:23:12.14Z" }, + { url = "https://files.pythonhosted.org/packages/0d/cd/16aec9f0da4793e98e6b54778a5fbce4f375c6646fe662e80600b8797379/pillow-12.0.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:3e42edad50b6909089750e65c91aa09aaf1e0a71310d383f11321b27c224ed8a", size = 3576812, upload-time = "2025-10-15T18:23:13.962Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b7/13957fda356dc46339298b351cae0d327704986337c3c69bb54628c88155/pillow-12.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e5d8efac84c9afcb40914ab49ba063d94f5dbdf5066db4482c66a992f47a3a3b", size = 5252689, upload-time = "2025-10-15T18:23:15.562Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f5/eae31a306341d8f331f43edb2e9122c7661b975433de5e447939ae61c5da/pillow-12.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:266cd5f2b63ff316d5a1bba46268e603c9caf5606d44f38c2873c380950576ad", size = 4650186, upload-time = "2025-10-15T18:23:17.379Z" }, + { url = "https://files.pythonhosted.org/packages/86/62/2a88339aa40c4c77e79108facbd307d6091e2c0eb5b8d3cf4977cfca2fe6/pillow-12.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58eea5ebe51504057dd95c5b77d21700b77615ab0243d8152793dc00eb4faf01", size = 6230308, upload-time = "2025-10-15T18:23:18.971Z" }, + { url = "https://files.pythonhosted.org/packages/c7/33/5425a8992bcb32d1cb9fa3dd39a89e613d09a22f2c8083b7bf43c455f760/pillow-12.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f13711b1a5ba512d647a0e4ba79280d3a9a045aaf7e0cc6fbe96b91d4cdf6b0c", size = 8039222, upload-time = "2025-10-15T18:23:20.909Z" }, + { url = "https://files.pythonhosted.org/packages/d8/61/3f5d3b35c5728f37953d3eec5b5f3e77111949523bd2dd7f31a851e50690/pillow-12.0.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6846bd2d116ff42cba6b646edf5bf61d37e5cbd256425fa089fee4ff5c07a99e", size = 6346657, upload-time = "2025-10-15T18:23:23.077Z" }, + { url = "https://files.pythonhosted.org/packages/3a/be/ee90a3d79271227e0f0a33c453531efd6ed14b2e708596ba5dd9be948da3/pillow-12.0.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c98fa880d695de164b4135a52fd2e9cd7b7c90a9d8ac5e9e443a24a95ef9248e", size = 7038482, upload-time = "2025-10-15T18:23:25.005Z" }, + { url = "https://files.pythonhosted.org/packages/44/34/a16b6a4d1ad727de390e9bd9f19f5f669e079e5826ec0f329010ddea492f/pillow-12.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa3ed2a29a9e9d2d488b4da81dcb54720ac3104a20bf0bd273f1e4648aff5af9", size = 6461416, upload-time = "2025-10-15T18:23:27.009Z" }, + { url = "https://files.pythonhosted.org/packages/b6/39/1aa5850d2ade7d7ba9f54e4e4c17077244ff7a2d9e25998c38a29749eb3f/pillow-12.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d034140032870024e6b9892c692fe2968493790dd57208b2c37e3fb35f6df3ab", size = 7131584, upload-time = "2025-10-15T18:23:29.752Z" }, + { url = "https://files.pythonhosted.org/packages/bf/db/4fae862f8fad0167073a7733973bfa955f47e2cac3dc3e3e6257d10fab4a/pillow-12.0.0-cp314-cp314-win32.whl", hash = "sha256:1b1b133e6e16105f524a8dec491e0586d072948ce15c9b914e41cdadd209052b", size = 6400621, upload-time = "2025-10-15T18:23:32.06Z" }, + { url = "https://files.pythonhosted.org/packages/2b/24/b350c31543fb0107ab2599464d7e28e6f856027aadda995022e695313d94/pillow-12.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:8dc232e39d409036af549c86f24aed8273a40ffa459981146829a324e0848b4b", size = 7142916, upload-time = "2025-10-15T18:23:34.71Z" }, + { url = "https://files.pythonhosted.org/packages/0f/9b/0ba5a6fd9351793996ef7487c4fdbde8d3f5f75dbedc093bb598648fddf0/pillow-12.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:d52610d51e265a51518692045e372a4c363056130d922a7351429ac9f27e70b0", size = 2523836, upload-time = "2025-10-15T18:23:36.967Z" }, + { url = "https://files.pythonhosted.org/packages/f5/7a/ceee0840aebc579af529b523d530840338ecf63992395842e54edc805987/pillow-12.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1979f4566bb96c1e50a62d9831e2ea2d1211761e5662afc545fa766f996632f6", size = 5255092, upload-time = "2025-10-15T18:23:38.573Z" }, + { url = "https://files.pythonhosted.org/packages/44/76/20776057b4bfd1aef4eeca992ebde0f53a4dce874f3ae693d0ec90a4f79b/pillow-12.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2e4b27a6e15b04832fe9bf292b94b5ca156016bbc1ea9c2c20098a0320d6cf6", size = 4653158, upload-time = "2025-10-15T18:23:40.238Z" }, + { url = "https://files.pythonhosted.org/packages/82/3f/d9ff92ace07be8836b4e7e87e6a4c7a8318d47c2f1463ffcf121fc57d9cb/pillow-12.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fb3096c30df99fd01c7bf8e544f392103d0795b9f98ba71a8054bcbf56b255f1", size = 6267882, upload-time = "2025-10-15T18:23:42.434Z" }, + { url = "https://files.pythonhosted.org/packages/9f/7a/4f7ff87f00d3ad33ba21af78bfcd2f032107710baf8280e3722ceec28cda/pillow-12.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7438839e9e053ef79f7112c881cef684013855016f928b168b81ed5835f3e75e", size = 8071001, upload-time = "2025-10-15T18:23:44.29Z" }, + { url = "https://files.pythonhosted.org/packages/75/87/fcea108944a52dad8cca0715ae6247e271eb80459364a98518f1e4f480c1/pillow-12.0.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d5c411a8eaa2299322b647cd932586b1427367fd3184ffbb8f7a219ea2041ca", size = 6380146, upload-time = "2025-10-15T18:23:46.065Z" }, + { url = "https://files.pythonhosted.org/packages/91/52/0d31b5e571ef5fd111d2978b84603fce26aba1b6092f28e941cb46570745/pillow-12.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e091d464ac59d2c7ad8e7e08105eaf9dafbc3883fd7265ffccc2baad6ac925", size = 7067344, upload-time = "2025-10-15T18:23:47.898Z" }, + { url = "https://files.pythonhosted.org/packages/7b/f4/2dd3d721f875f928d48e83bb30a434dee75a2531bca839bb996bb0aa5a91/pillow-12.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:792a2c0be4dcc18af9d4a2dfd8a11a17d5e25274a1062b0ec1c2d79c76f3e7f8", size = 6491864, upload-time = "2025-10-15T18:23:49.607Z" }, + { url = "https://files.pythonhosted.org/packages/30/4b/667dfcf3d61fc309ba5a15b141845cece5915e39b99c1ceab0f34bf1d124/pillow-12.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:afbefa430092f71a9593a99ab6a4e7538bc9eabbf7bf94f91510d3503943edc4", size = 7158911, upload-time = "2025-10-15T18:23:51.351Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2f/16cabcc6426c32218ace36bf0d55955e813f2958afddbf1d391849fee9d1/pillow-12.0.0-cp314-cp314t-win32.whl", hash = "sha256:3830c769decf88f1289680a59d4f4c46c72573446352e2befec9a8512104fa52", size = 6408045, upload-time = "2025-10-15T18:23:53.177Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/e29aa0c9c666cf787628d3f0dcf379f4791fba79f4936d02f8b37165bdf8/pillow-12.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:905b0365b210c73afb0ebe9101a32572152dfd1c144c7e28968a331b9217b94a", size = 7148282, upload-time = "2025-10-15T18:23:55.316Z" }, + { url = "https://files.pythonhosted.org/packages/c1/70/6b41bdcddf541b437bbb9f47f94d2db5d9ddef6c37ccab8c9107743748a4/pillow-12.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:99353a06902c2e43b43e8ff74ee65a7d90307d82370604746738a1e0661ccca7", size = 2525630, upload-time = "2025-10-15T18:23:57.149Z" }, + { url = "https://files.pythonhosted.org/packages/1d/b3/582327e6c9f86d037b63beebe981425d6811104cb443e8193824ef1a2f27/pillow-12.0.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b22bd8c974942477156be55a768f7aa37c46904c175be4e158b6a86e3a6b7ca8", size = 5215068, upload-time = "2025-10-15T18:23:59.594Z" }, + { url = "https://files.pythonhosted.org/packages/fd/d6/67748211d119f3b6540baf90f92fae73ae51d5217b171b0e8b5f7e5d558f/pillow-12.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:805ebf596939e48dbb2e4922a1d3852cfc25c38160751ce02da93058b48d252a", size = 4614994, upload-time = "2025-10-15T18:24:01.669Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e1/f8281e5d844c41872b273b9f2c34a4bf64ca08905668c8ae730eedc7c9fa/pillow-12.0.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cae81479f77420d217def5f54b5b9d279804d17e982e0f2fa19b1d1e14ab5197", size = 5246639, upload-time = "2025-10-15T18:24:03.403Z" }, + { url = "https://files.pythonhosted.org/packages/94/5a/0d8ab8ffe8a102ff5df60d0de5af309015163bf710c7bb3e8311dd3b3ad0/pillow-12.0.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeaefa96c768fc66818730b952a862235d68825c178f1b3ffd4efd7ad2edcb7c", size = 6986839, upload-time = "2025-10-15T18:24:05.344Z" }, + { url = "https://files.pythonhosted.org/packages/20/2e/3434380e8110b76cd9eb00a363c484b050f949b4bbe84ba770bb8508a02c/pillow-12.0.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09f2d0abef9e4e2f349305a4f8cc784a8a6c2f58a8c4892eea13b10a943bd26e", size = 5313505, upload-time = "2025-10-15T18:24:07.137Z" }, + { url = "https://files.pythonhosted.org/packages/57/ca/5a9d38900d9d74785141d6580950fe705de68af735ff6e727cb911b64740/pillow-12.0.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bdee52571a343d721fb2eb3b090a82d959ff37fc631e3f70422e0c2e029f3e76", size = 5963654, upload-time = "2025-10-15T18:24:09.579Z" }, + { url = "https://files.pythonhosted.org/packages/95/7e/f896623c3c635a90537ac093c6a618ebe1a90d87206e42309cb5d98a1b9e/pillow-12.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b290fd8aa38422444d4b50d579de197557f182ef1068b75f5aa8558638b8d0a5", size = 6997850, upload-time = "2025-10-15T18:24:11.495Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "preshed" +version = "3.0.10" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cymem" }, + { name = "murmurhash" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4d/3a/db814f67a05b6d7f9c15d38edef5ec9b21415710705b393883de92aee5ef/preshed-3.0.10.tar.gz", hash = "sha256:5a5c8e685e941f4ffec97f1fbf32694b8107858891a4bc34107fac981d8296ff", size = 15039, upload-time = "2025-05-26T15:18:33.612Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/66/12/3bfd7790481513d71a281a3a7194a6d7aa9a59289a109253e78d9bcedcec/preshed-3.0.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:14593c32e6705fda0fd54684293ca079530418bb1fb036dcbaa6c0ef0f144b7d", size = 131102, upload-time = "2025-05-26T15:17:41.762Z" }, + { url = "https://files.pythonhosted.org/packages/e4/bf/54635387524315fe40b1f3d1688a5ad369f59a4e3a377b0da6e8a3ecba30/preshed-3.0.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba1960a3996678aded882260133853e19e3a251d9f35a19c9d7d830c4238c4eb", size = 127302, upload-time = "2025-05-26T15:17:43.263Z" }, + { url = "https://files.pythonhosted.org/packages/fe/df/d057705c9c6aff877ee687f612f242006750f165c0e557f6075fe913a8e3/preshed-3.0.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0830c0a262015be743a01455a1da5963750afed1bde2395590b01af3b7da2741", size = 793737, upload-time = "2025-05-26T15:17:44.736Z" }, + { url = "https://files.pythonhosted.org/packages/c4/73/9206a60e59e81a259d49273f95307821f5e88c84c400533ed0cb9a8093af/preshed-3.0.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:165dda5862c28e77ee1f3feabad98d4ebb65345f458b5626596b92fd20a65275", size = 795131, upload-time = "2025-05-26T15:17:46.382Z" }, + { url = "https://files.pythonhosted.org/packages/25/18/02a40bcb13ae6c1ca3a859a709354621b45c83857994943c9c409f85f183/preshed-3.0.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e88e4c7fbbfa7c23a90d7d0cbe27e4c5fa2fd742ef1be09c153f9ccd2c600098", size = 777924, upload-time = "2025-05-26T15:17:48.184Z" }, + { url = "https://files.pythonhosted.org/packages/11/13/bb2db0f037fc659494fbe964255f80fbca7e5e4154137e9855619e3543d9/preshed-3.0.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:87780ae00def0c97130c9d1652295ec8362c2e4ca553673b64fe0dc7b321a382", size = 796024, upload-time = "2025-05-26T15:17:49.568Z" }, + { url = "https://files.pythonhosted.org/packages/99/ab/7187df84a32f02d987b689f4bbb1ad77304bdc8129d8fed483b8ebde113d/preshed-3.0.10-cp310-cp310-win_amd64.whl", hash = "sha256:32496f216255a6cbdd60965dde29ff42ed8fc2d77968c28ae875e3856c6fa01a", size = 117429, upload-time = "2025-05-26T15:17:51.091Z" }, + { url = "https://files.pythonhosted.org/packages/08/99/c3709638f687da339504d1daeca48604cadb338bf3556a1484d1f0cd95e6/preshed-3.0.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d96c4fe2b41c1cdcc8c4fc1fdb10f922a6095c0430a3ebe361fe62c78902d068", size = 131486, upload-time = "2025-05-26T15:17:52.231Z" }, + { url = "https://files.pythonhosted.org/packages/e0/27/0fd36b63caa8bbf57b31a121d9565d385bbd7521771d4eb93e17d326873d/preshed-3.0.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cb01ea930b96f3301526a2ab26f41347d07555e4378c4144c6b7645074f2ebb0", size = 127938, upload-time = "2025-05-26T15:17:54.19Z" }, + { url = "https://files.pythonhosted.org/packages/90/54/6a876d9cc8d401a9c1fb6bb8ca5a31b3664d0bcb888a9016258a1ae17344/preshed-3.0.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dd1f0a7b7d150e229d073fd4fe94f72610cae992e907cee74687c4695873a98", size = 842263, upload-time = "2025-05-26T15:17:55.398Z" }, + { url = "https://files.pythonhosted.org/packages/1c/7d/ff19f74d15ee587905bafa3582883cfe2f72b574e6d691ee64dc690dc276/preshed-3.0.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fd7b350c280137f324cd447afbf6ba9a849af0e8898850046ac6f34010e08bd", size = 842913, upload-time = "2025-05-26T15:17:56.687Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3a/1c345a26463345557705b61965e1e0a732cc0e9c6dfd4787845dbfa50b4a/preshed-3.0.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cf6a5fdc89ad06079aa6ee63621e417d4f4cf2a3d8b63c72728baad35a9ff641", size = 820548, upload-time = "2025-05-26T15:17:58.057Z" }, + { url = "https://files.pythonhosted.org/packages/7f/6b/71f25e2b7a23dba168f43edfae0bb508552dbef89114ce65c73f2ea7172f/preshed-3.0.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b4c29a7bd66985808ad181c9ad05205a6aa7400cd0f98426acd7bc86588b93f8", size = 840379, upload-time = "2025-05-26T15:17:59.565Z" }, + { url = "https://files.pythonhosted.org/packages/3a/86/d8f32b0b31a36ee8770a9b1a95321430e364cd0ba4bfebb7348aed2f198d/preshed-3.0.10-cp311-cp311-win_amd64.whl", hash = "sha256:1367c1fd6f44296305315d4e1c3fe3171787d4d01c1008a76bc9466bd79c3249", size = 117655, upload-time = "2025-05-26T15:18:00.836Z" }, + { url = "https://files.pythonhosted.org/packages/c3/14/322a4f58bc25991a87f216acb1351800739b0794185d27508ee86c35f382/preshed-3.0.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6e9c46933d55c8898c8f7a6019a8062cd87ef257b075ada2dd5d1e57810189ea", size = 131367, upload-time = "2025-05-26T15:18:02.408Z" }, + { url = "https://files.pythonhosted.org/packages/38/80/67507653c35620cace913f617df6d6f658b87e8da83087b851557d65dd86/preshed-3.0.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5c4ebc4f8ef0114d55f2ffdce4965378129c7453d0203664aeeb03055572d9e4", size = 126535, upload-time = "2025-05-26T15:18:03.589Z" }, + { url = "https://files.pythonhosted.org/packages/db/b1/ab4f811aeaf20af0fa47148c1c54b62d7e8120d59025bd0a3f773bb67725/preshed-3.0.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ab5ab4c6dfd3746fb4328e7fbeb2a0544416b872db02903bfac18e6f5cd412f", size = 864907, upload-time = "2025-05-26T15:18:04.794Z" }, + { url = "https://files.pythonhosted.org/packages/fb/db/fe37c1f99cfb26805dd89381ddd54901307feceb267332eaaca228e9f9c1/preshed-3.0.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40586fd96ae3974c552a7cd78781b6844ecb1559ee7556586f487058cf13dd96", size = 869329, upload-time = "2025-05-26T15:18:06.353Z" }, + { url = "https://files.pythonhosted.org/packages/a7/fd/efb6a6233d1cd969966f3f65bdd8e662579c3d83114e5c356cec1927b1f7/preshed-3.0.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a606c24cda931306b98e0edfafed3309bffcf8d6ecfe07804db26024c4f03cd6", size = 846829, upload-time = "2025-05-26T15:18:07.716Z" }, + { url = "https://files.pythonhosted.org/packages/14/49/0e4ce5db3bf86b081abb08a404fb37b7c2dbfd7a73ec6c0bc71b650307eb/preshed-3.0.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:394015566f9354738be903447039e8dbc6d93ba5adf091af694eb03c4e726b1e", size = 874008, upload-time = "2025-05-26T15:18:09.364Z" }, + { url = "https://files.pythonhosted.org/packages/6f/17/76d6593fc2d055d4e413b68a8c87b70aa9b7697d4972cb8062559edcf6e9/preshed-3.0.10-cp312-cp312-win_amd64.whl", hash = "sha256:fd7e38225937e580420c84d1996dde9b4f726aacd9405093455c3a2fa60fede5", size = 116701, upload-time = "2025-05-26T15:18:11.905Z" }, + { url = "https://files.pythonhosted.org/packages/bf/5e/87671bc58c4f6c8cf0a5601ccd74b8bb50281ff28aa4ab3e3cad5cd9d06a/preshed-3.0.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:23e6e0581a517597f3f76bc24a4cdb0ba5509933d4f61c34fca49649dd71edf9", size = 129184, upload-time = "2025-05-26T15:18:13.331Z" }, + { url = "https://files.pythonhosted.org/packages/92/69/b3969a3c95778def5bf5126484a1f7d2ad324d1040077f55f56e027d8ea4/preshed-3.0.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:574e6d6056981540310ff181b47a2912f4bddc91bcace3c7a9c6726eafda24ca", size = 124258, upload-time = "2025-05-26T15:18:14.497Z" }, + { url = "https://files.pythonhosted.org/packages/32/df/6e828ec4565bf33bd4803a3eb3b1102830b739143e5d6c132bf7181a58ec/preshed-3.0.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd658dd73e853d1bb5597976a407feafa681b9d6155bc9bc7b4c2acc2a6ee96", size = 825445, upload-time = "2025-05-26T15:18:15.71Z" }, + { url = "https://files.pythonhosted.org/packages/05/3d/478b585f304920e51f328c9231e22f30dc64baa68e079e08a46ab72be738/preshed-3.0.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b95396046328ffb461a68859ce2141aca4815b8624167832d28ced70d541626", size = 831690, upload-time = "2025-05-26T15:18:17.08Z" }, + { url = "https://files.pythonhosted.org/packages/c3/65/938f21f77227e8d398d46fb10b9d1b3467be859468ce8db138fc3d50589c/preshed-3.0.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3e6728b2028bbe79565eb6cf676b5bae5ce1f9cc56e4bf99bb28ce576f88054d", size = 808593, upload-time = "2025-05-26T15:18:18.535Z" }, + { url = "https://files.pythonhosted.org/packages/6c/1c/2a3961fc88bc72300ff7e4ca54689bda90d2d77cc994167cc09a310480b6/preshed-3.0.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c4ef96cb28bf5f08de9c070143113e168efccbb68fd4961e7d445f734c051a97", size = 837333, upload-time = "2025-05-26T15:18:19.937Z" }, + { url = "https://files.pythonhosted.org/packages/fa/8c/d3e30f80b2ef21f267f09f0b7d18995adccc928ede5b73ea3fe54e1303f4/preshed-3.0.10-cp313-cp313-win_amd64.whl", hash = "sha256:97e0e2edfd25a7dfba799b49b3c5cc248ad0318a76edd9d5fd2c82aa3d5c64ed", size = 115769, upload-time = "2025-05-26T15:18:21.842Z" }, +] + +[[package]] +name = "propcache" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/0e/934b541323035566a9af292dba85a195f7b78179114f2c6ebb24551118a9/propcache-0.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c2d1fa3201efaf55d730400d945b5b3ab6e672e100ba0f9a409d950ab25d7db", size = 79534, upload-time = "2025-10-08T19:46:02.083Z" }, + { url = "https://files.pythonhosted.org/packages/a1/6b/db0d03d96726d995dc7171286c6ba9d8d14251f37433890f88368951a44e/propcache-0.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1eb2994229cc8ce7fe9b3db88f5465f5fd8651672840b2e426b88cdb1a30aac8", size = 45526, upload-time = "2025-10-08T19:46:03.884Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c3/82728404aea669e1600f304f2609cde9e665c18df5a11cdd57ed73c1dceb/propcache-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:66c1f011f45a3b33d7bcb22daed4b29c0c9e2224758b6be00686731e1b46f925", size = 47263, upload-time = "2025-10-08T19:46:05.405Z" }, + { url = "https://files.pythonhosted.org/packages/df/1b/39313ddad2bf9187a1432654c38249bab4562ef535ef07f5eb6eb04d0b1b/propcache-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9a52009f2adffe195d0b605c25ec929d26b36ef986ba85244891dee3b294df21", size = 201012, upload-time = "2025-10-08T19:46:07.165Z" }, + { url = "https://files.pythonhosted.org/packages/5b/01/f1d0b57d136f294a142acf97f4ed58c8e5b974c21e543000968357115011/propcache-0.4.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5d4e2366a9c7b837555cf02fb9be2e3167d333aff716332ef1b7c3a142ec40c5", size = 209491, upload-time = "2025-10-08T19:46:08.909Z" }, + { url = "https://files.pythonhosted.org/packages/a1/c8/038d909c61c5bb039070b3fb02ad5cccdb1dde0d714792e251cdb17c9c05/propcache-0.4.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9d2b6caef873b4f09e26ea7e33d65f42b944837563a47a94719cc3544319a0db", size = 215319, upload-time = "2025-10-08T19:46:10.7Z" }, + { url = "https://files.pythonhosted.org/packages/08/57/8c87e93142b2c1fa2408e45695205a7ba05fb5db458c0bf5c06ba0e09ea6/propcache-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b16ec437a8c8a965ecf95739448dd938b5c7f56e67ea009f4300d8df05f32b7", size = 196856, upload-time = "2025-10-08T19:46:12.003Z" }, + { url = "https://files.pythonhosted.org/packages/42/df/5615fec76aa561987a534759b3686008a288e73107faa49a8ae5795a9f7a/propcache-0.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:296f4c8ed03ca7476813fe666c9ea97869a8d7aec972618671b33a38a5182ef4", size = 193241, upload-time = "2025-10-08T19:46:13.495Z" }, + { url = "https://files.pythonhosted.org/packages/d5/21/62949eb3a7a54afe8327011c90aca7e03547787a88fb8bd9726806482fea/propcache-0.4.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:1f0978529a418ebd1f49dad413a2b68af33f85d5c5ca5c6ca2a3bed375a7ac60", size = 190552, upload-time = "2025-10-08T19:46:14.938Z" }, + { url = "https://files.pythonhosted.org/packages/30/ee/ab4d727dd70806e5b4de96a798ae7ac6e4d42516f030ee60522474b6b332/propcache-0.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fd138803047fb4c062b1c1dd95462f5209456bfab55c734458f15d11da288f8f", size = 200113, upload-time = "2025-10-08T19:46:16.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0b/38b46208e6711b016aa8966a3ac793eee0d05c7159d8342aa27fc0bc365e/propcache-0.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8c9b3cbe4584636d72ff556d9036e0c9317fa27b3ac1f0f558e7e84d1c9c5900", size = 200778, upload-time = "2025-10-08T19:46:18.023Z" }, + { url = "https://files.pythonhosted.org/packages/cf/81/5abec54355ed344476bee711e9f04815d4b00a311ab0535599204eecc257/propcache-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f93243fdc5657247533273ac4f86ae106cc6445a0efacb9a1bfe982fcfefd90c", size = 193047, upload-time = "2025-10-08T19:46:19.449Z" }, + { url = "https://files.pythonhosted.org/packages/ec/b6/1f237c04e32063cb034acd5f6ef34ef3a394f75502e72703545631ab1ef6/propcache-0.4.1-cp310-cp310-win32.whl", hash = "sha256:a0ee98db9c5f80785b266eb805016e36058ac72c51a064040f2bc43b61101cdb", size = 38093, upload-time = "2025-10-08T19:46:20.643Z" }, + { url = "https://files.pythonhosted.org/packages/a6/67/354aac4e0603a15f76439caf0427781bcd6797f370377f75a642133bc954/propcache-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cdb7988c4e5ac7f6d175a28a9aa0c94cb6f2ebe52756a3c0cda98d2809a9e37", size = 41638, upload-time = "2025-10-08T19:46:21.935Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e1/74e55b9fd1a4c209ff1a9a824bf6c8b3d1fc5a1ac3eabe23462637466785/propcache-0.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:d82ad62b19645419fe79dd63b3f9253e15b30e955c0170e5cebc350c1844e581", size = 38229, upload-time = "2025-10-08T19:46:23.368Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d4/4e2c9aaf7ac2242b9358f98dccd8f90f2605402f5afeff6c578682c2c491/propcache-0.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:60a8fda9644b7dfd5dece8c61d8a85e271cb958075bfc4e01083c148b61a7caf", size = 80208, upload-time = "2025-10-08T19:46:24.597Z" }, + { url = "https://files.pythonhosted.org/packages/c2/21/d7b68e911f9c8e18e4ae43bdbc1e1e9bbd971f8866eb81608947b6f585ff/propcache-0.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c30b53e7e6bda1d547cabb47c825f3843a0a1a42b0496087bb58d8fedf9f41b5", size = 45777, upload-time = "2025-10-08T19:46:25.733Z" }, + { url = "https://files.pythonhosted.org/packages/d3/1d/11605e99ac8ea9435651ee71ab4cb4bf03f0949586246476a25aadfec54a/propcache-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6918ecbd897443087a3b7cd978d56546a812517dcaaca51b49526720571fa93e", size = 47647, upload-time = "2025-10-08T19:46:27.304Z" }, + { url = "https://files.pythonhosted.org/packages/58/1a/3c62c127a8466c9c843bccb503d40a273e5cc69838805f322e2826509e0d/propcache-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3d902a36df4e5989763425a8ab9e98cd8ad5c52c823b34ee7ef307fd50582566", size = 214929, upload-time = "2025-10-08T19:46:28.62Z" }, + { url = "https://files.pythonhosted.org/packages/56/b9/8fa98f850960b367c4b8fe0592e7fc341daa7a9462e925228f10a60cf74f/propcache-0.4.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a9695397f85973bb40427dedddf70d8dc4a44b22f1650dd4af9eedf443d45165", size = 221778, upload-time = "2025-10-08T19:46:30.358Z" }, + { url = "https://files.pythonhosted.org/packages/46/a6/0ab4f660eb59649d14b3d3d65c439421cf2f87fe5dd68591cbe3c1e78a89/propcache-0.4.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2bb07ffd7eaad486576430c89f9b215f9e4be68c4866a96e97db9e97fead85dc", size = 228144, upload-time = "2025-10-08T19:46:32.607Z" }, + { url = "https://files.pythonhosted.org/packages/52/6a/57f43e054fb3d3a56ac9fc532bc684fc6169a26c75c353e65425b3e56eef/propcache-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd6f30fdcf9ae2a70abd34da54f18da086160e4d7d9251f81f3da0ff84fc5a48", size = 210030, upload-time = "2025-10-08T19:46:33.969Z" }, + { url = "https://files.pythonhosted.org/packages/40/e2/27e6feebb5f6b8408fa29f5efbb765cd54c153ac77314d27e457a3e993b7/propcache-0.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fc38cba02d1acba4e2869eef1a57a43dfbd3d49a59bf90dda7444ec2be6a5570", size = 208252, upload-time = "2025-10-08T19:46:35.309Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f8/91c27b22ccda1dbc7967f921c42825564fa5336a01ecd72eb78a9f4f53c2/propcache-0.4.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:67fad6162281e80e882fb3ec355398cf72864a54069d060321f6cd0ade95fe85", size = 202064, upload-time = "2025-10-08T19:46:36.993Z" }, + { url = "https://files.pythonhosted.org/packages/f2/26/7f00bd6bd1adba5aafe5f4a66390f243acab58eab24ff1a08bebb2ef9d40/propcache-0.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f10207adf04d08bec185bae14d9606a1444715bc99180f9331c9c02093e1959e", size = 212429, upload-time = "2025-10-08T19:46:38.398Z" }, + { url = "https://files.pythonhosted.org/packages/84/89/fd108ba7815c1117ddca79c228f3f8a15fc82a73bca8b142eb5de13b2785/propcache-0.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e9b0d8d0845bbc4cfcdcbcdbf5086886bc8157aa963c31c777ceff7846c77757", size = 216727, upload-time = "2025-10-08T19:46:39.732Z" }, + { url = "https://files.pythonhosted.org/packages/79/37/3ec3f7e3173e73f1d600495d8b545b53802cbf35506e5732dd8578db3724/propcache-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:981333cb2f4c1896a12f4ab92a9cc8f09ea664e9b7dbdc4eff74627af3a11c0f", size = 205097, upload-time = "2025-10-08T19:46:41.025Z" }, + { url = "https://files.pythonhosted.org/packages/61/b0/b2631c19793f869d35f47d5a3a56fb19e9160d3c119f15ac7344fc3ccae7/propcache-0.4.1-cp311-cp311-win32.whl", hash = "sha256:f1d2f90aeec838a52f1c1a32fe9a619fefd5e411721a9117fbf82aea638fe8a1", size = 38084, upload-time = "2025-10-08T19:46:42.693Z" }, + { url = "https://files.pythonhosted.org/packages/f4/78/6cce448e2098e9f3bfc91bb877f06aa24b6ccace872e39c53b2f707c4648/propcache-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:364426a62660f3f699949ac8c621aad6977be7126c5807ce48c0aeb8e7333ea6", size = 41637, upload-time = "2025-10-08T19:46:43.778Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e9/754f180cccd7f51a39913782c74717c581b9cc8177ad0e949f4d51812383/propcache-0.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:e53f3a38d3510c11953f3e6a33f205c6d1b001129f972805ca9b42fc308bc239", size = 38064, upload-time = "2025-10-08T19:46:44.872Z" }, + { url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" }, + { url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" }, + { url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" }, + { url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" }, + { url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" }, + { url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" }, + { url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" }, + { url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" }, + { url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" }, + { url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" }, + { url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" }, + { url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" }, + { url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" }, + { url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" }, + { url = "https://files.pythonhosted.org/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" }, + { url = "https://files.pythonhosted.org/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" }, + { url = "https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" }, + { url = "https://files.pythonhosted.org/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" }, + { url = "https://files.pythonhosted.org/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" }, + { url = "https://files.pythonhosted.org/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" }, + { url = "https://files.pythonhosted.org/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" }, + { url = "https://files.pythonhosted.org/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" }, + { url = "https://files.pythonhosted.org/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" }, + { url = "https://files.pythonhosted.org/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" }, + { url = "https://files.pythonhosted.org/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" }, + { url = "https://files.pythonhosted.org/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" }, + { url = "https://files.pythonhosted.org/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" }, + { url = "https://files.pythonhosted.org/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" }, + { url = "https://files.pythonhosted.org/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" }, + { url = "https://files.pythonhosted.org/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" }, + { url = "https://files.pythonhosted.org/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" }, + { url = "https://files.pythonhosted.org/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" }, + { url = "https://files.pythonhosted.org/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" }, + { url = "https://files.pythonhosted.org/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" }, + { url = "https://files.pythonhosted.org/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" }, + { url = "https://files.pythonhosted.org/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" }, + { url = "https://files.pythonhosted.org/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", size = 78152, upload-time = "2025-10-08T19:47:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", size = 44869, upload-time = "2025-10-08T19:47:52.594Z" }, + { url = "https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", size = 46596, upload-time = "2025-10-08T19:47:54.073Z" }, + { url = "https://files.pythonhosted.org/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", size = 206981, upload-time = "2025-10-08T19:47:55.715Z" }, + { url = "https://files.pythonhosted.org/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", size = 211490, upload-time = "2025-10-08T19:47:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", size = 215371, upload-time = "2025-10-08T19:47:59.317Z" }, + { url = "https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", size = 201424, upload-time = "2025-10-08T19:48:00.67Z" }, + { url = "https://files.pythonhosted.org/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", size = 197566, upload-time = "2025-10-08T19:48:02.604Z" }, + { url = "https://files.pythonhosted.org/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", size = 193130, upload-time = "2025-10-08T19:48:04.499Z" }, + { url = "https://files.pythonhosted.org/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", size = 202625, upload-time = "2025-10-08T19:48:06.213Z" }, + { url = "https://files.pythonhosted.org/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", size = 204209, upload-time = "2025-10-08T19:48:08.432Z" }, + { url = "https://files.pythonhosted.org/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", size = 197797, upload-time = "2025-10-08T19:48:09.968Z" }, + { url = "https://files.pythonhosted.org/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", size = 38140, upload-time = "2025-10-08T19:48:11.232Z" }, + { url = "https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", size = 41257, upload-time = "2025-10-08T19:48:12.707Z" }, + { url = "https://files.pythonhosted.org/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", size = 38097, upload-time = "2025-10-08T19:48:13.923Z" }, + { url = "https://files.pythonhosted.org/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", size = 81455, upload-time = "2025-10-08T19:48:15.16Z" }, + { url = "https://files.pythonhosted.org/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", size = 46372, upload-time = "2025-10-08T19:48:16.424Z" }, + { url = "https://files.pythonhosted.org/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", size = 48411, upload-time = "2025-10-08T19:48:17.577Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", size = 275712, upload-time = "2025-10-08T19:48:18.901Z" }, + { url = "https://files.pythonhosted.org/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", size = 273557, upload-time = "2025-10-08T19:48:20.762Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", size = 280015, upload-time = "2025-10-08T19:48:22.592Z" }, + { url = "https://files.pythonhosted.org/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", size = 262880, upload-time = "2025-10-08T19:48:23.947Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", size = 260938, upload-time = "2025-10-08T19:48:25.656Z" }, + { url = "https://files.pythonhosted.org/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", size = 247641, upload-time = "2025-10-08T19:48:27.207Z" }, + { url = "https://files.pythonhosted.org/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", size = 262510, upload-time = "2025-10-08T19:48:28.65Z" }, + { url = "https://files.pythonhosted.org/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", size = 263161, upload-time = "2025-10-08T19:48:30.133Z" }, + { url = "https://files.pythonhosted.org/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", size = 257393, upload-time = "2025-10-08T19:48:31.567Z" }, + { url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" }, + { url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" }, +] + +[[package]] +name = "psutil" +version = "7.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/ec/7b8e6b9b1d22708138630ef34c53ab2b61032c04f16adfdbb96791c8c70c/psutil-7.1.2.tar.gz", hash = "sha256:aa225cdde1335ff9684708ee8c72650f6598d5ed2114b9a7c5802030b1785018", size = 487424, upload-time = "2025-10-25T10:46:34.931Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/d9/b56cc9f883140ac10021a8c9b0f4e16eed1ba675c22513cdcbce3ba64014/psutil-7.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0cc5c6889b9871f231ed5455a9a02149e388fffcb30b607fb7a8896a6d95f22e", size = 238575, upload-time = "2025-10-25T10:46:38.728Z" }, + { url = "https://files.pythonhosted.org/packages/36/eb/28d22de383888deb252c818622196e709da98816e296ef95afda33f1c0a2/psutil-7.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8e9e77a977208d84aa363a4a12e0f72189d58bbf4e46b49aae29a2c6e93ef206", size = 239297, upload-time = "2025-10-25T10:46:41.347Z" }, + { url = "https://files.pythonhosted.org/packages/89/5d/220039e2f28cc129626e54d63892ab05c0d56a29818bfe7268dcb5008932/psutil-7.1.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d9623a5e4164d2220ecceb071f4b333b3c78866141e8887c072129185f41278", size = 280420, upload-time = "2025-10-25T10:46:44.122Z" }, + { url = "https://files.pythonhosted.org/packages/ba/7a/286f0e1c167445b2ef4a6cbdfc8c59fdb45a5a493788950cf8467201dc73/psutil-7.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:364b1c10fe4ed59c89ec49e5f1a70da353b27986fa8233b4b999df4742a5ee2f", size = 283049, upload-time = "2025-10-25T10:46:47.095Z" }, + { url = "https://files.pythonhosted.org/packages/aa/cc/7eb93260794a42e39b976f3a4dde89725800b9f573b014fac142002a5c98/psutil-7.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f101ef84de7e05d41310e3ccbdd65a6dd1d9eed85e8aaf0758405d022308e204", size = 248713, upload-time = "2025-10-25T10:46:49.573Z" }, + { url = "https://files.pythonhosted.org/packages/ab/1a/0681a92b53366e01f0a099f5237d0c8a2f79d322ac589cccde5e30c8a4e2/psutil-7.1.2-cp313-cp313t-win_arm64.whl", hash = "sha256:20c00824048a95de67f00afedc7b08b282aa08638585b0206a9fb51f28f1a165", size = 244644, upload-time = "2025-10-25T10:46:51.924Z" }, + { url = "https://files.pythonhosted.org/packages/56/9e/f1c5c746b4ed5320952acd3002d3962fe36f30524c00ea79fdf954cc6779/psutil-7.1.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:e09cfe92aa8e22b1ec5e2d394820cf86c5dff6367ac3242366485dfa874d43bc", size = 238640, upload-time = "2025-10-25T10:46:54.089Z" }, + { url = "https://files.pythonhosted.org/packages/32/ee/fd26216a735395cc25c3899634e34aeb41fb1f3dbb44acc67d9e594be562/psutil-7.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:fa6342cf859c48b19df3e4aa170e4cfb64aadc50b11e06bb569c6c777b089c9e", size = 239303, upload-time = "2025-10-25T10:46:56.932Z" }, + { url = "https://files.pythonhosted.org/packages/3c/cd/7d96eaec4ef7742b845a9ce2759a2769ecce4ab7a99133da24abacbc9e41/psutil-7.1.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:625977443498ee7d6c1e63e93bacca893fd759a66c5f635d05e05811d23fb5ee", size = 281717, upload-time = "2025-10-25T10:46:59.116Z" }, + { url = "https://files.pythonhosted.org/packages/bc/1a/7f0b84bdb067d35fe7fade5fff888408688caf989806ce2d6dae08c72dd5/psutil-7.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a24bcd7b7f2918d934af0fb91859f621b873d6aa81267575e3655cd387572a7", size = 284575, upload-time = "2025-10-25T10:47:00.944Z" }, + { url = "https://files.pythonhosted.org/packages/de/05/7820ef8f7b275268917e0c750eada5834581206d9024ca88edce93c4b762/psutil-7.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:329f05610da6380982e6078b9d0881d9ab1e9a7eb7c02d833bfb7340aa634e31", size = 249491, upload-time = "2025-10-25T10:47:03.174Z" }, + { url = "https://files.pythonhosted.org/packages/db/9a/58de399c7cb58489f08498459ff096cd76b3f1ddc4f224ec2c5ef729c7d0/psutil-7.1.2-cp314-cp314t-win_arm64.whl", hash = "sha256:7b04c29e3c0c888e83ed4762b70f31e65c42673ea956cefa8ced0e31e185f582", size = 244880, upload-time = "2025-10-25T10:47:05.228Z" }, + { url = "https://files.pythonhosted.org/packages/ae/89/b9f8d47ddbc52d7301fc868e8224e5f44ed3c7f55e6d0f54ecaf5dd9ff5e/psutil-7.1.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c9ba5c19f2d46203ee8c152c7b01df6eec87d883cfd8ee1af2ef2727f6b0f814", size = 237244, upload-time = "2025-10-25T10:47:07.086Z" }, + { url = "https://files.pythonhosted.org/packages/c8/7a/8628c2f6b240680a67d73d8742bb9ff39b1820a693740e43096d5dcb01e5/psutil-7.1.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:2a486030d2fe81bec023f703d3d155f4823a10a47c36784c84f1cc7f8d39bedb", size = 238101, upload-time = "2025-10-25T10:47:09.523Z" }, + { url = "https://files.pythonhosted.org/packages/30/28/5e27f4d5a0e347f8e3cc16cd7d35533dbce086c95807f1f0e9cd77e26c10/psutil-7.1.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3efd8fc791492e7808a51cb2b94889db7578bfaea22df931424f874468e389e3", size = 258675, upload-time = "2025-10-25T10:47:11.082Z" }, + { url = "https://files.pythonhosted.org/packages/e5/5c/79cf60c9acf36d087f0db0f82066fca4a780e97e5b3a2e4c38209c03d170/psutil-7.1.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2aeb9b64f481b8eabfc633bd39e0016d4d8bbcd590d984af764d80bf0851b8a", size = 260203, upload-time = "2025-10-25T10:47:13.226Z" }, + { url = "https://files.pythonhosted.org/packages/f7/03/0a464404c51685dcb9329fdd660b1721e076ccd7b3d97dee066bcc9ffb15/psutil-7.1.2-cp37-abi3-win_amd64.whl", hash = "sha256:8e17852114c4e7996fe9da4745c2bdef001ebbf2f260dec406290e66628bdb91", size = 246714, upload-time = "2025-10-25T10:47:15.093Z" }, + { url = "https://files.pythonhosted.org/packages/6a/32/97ca2090f2f1b45b01b6aa7ae161cfe50671de097311975ca6eea3e7aabc/psutil-7.1.2-cp37-abi3-win_arm64.whl", hash = "sha256:3e988455e61c240cc879cb62a008c2699231bf3e3d061d7fce4234463fd2abb4", size = 243742, upload-time = "2025-10-25T10:47:17.302Z" }, +] + +[[package]] +name = "pyarrow" +version = "22.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/53/04a7fdc63e6056116c9ddc8b43bc28c12cdd181b85cbeadb79278475f3ae/pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", size = 1151151, upload-time = "2025-10-24T12:30:00.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/9b/cb3f7e0a345353def531ca879053e9ef6b9f38ed91aebcf68b09ba54dec0/pyarrow-22.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:77718810bd3066158db1e95a63c160ad7ce08c6b0710bc656055033e39cdad88", size = 34223968, upload-time = "2025-10-24T10:03:31.21Z" }, + { url = "https://files.pythonhosted.org/packages/6c/41/3184b8192a120306270c5307f105b70320fdaa592c99843c5ef78aaefdcf/pyarrow-22.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:44d2d26cda26d18f7af7db71453b7b783788322d756e81730acb98f24eb90ace", size = 35942085, upload-time = "2025-10-24T10:03:38.146Z" }, + { url = "https://files.pythonhosted.org/packages/d9/3d/a1eab2f6f08001f9fb714b8ed5cfb045e2fe3e3e3c0c221f2c9ed1e6d67d/pyarrow-22.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:b9d71701ce97c95480fecb0039ec5bb889e75f110da72005743451339262f4ce", size = 44964613, upload-time = "2025-10-24T10:03:46.516Z" }, + { url = "https://files.pythonhosted.org/packages/46/46/a1d9c24baf21cfd9ce994ac820a24608decf2710521b29223d4334985127/pyarrow-22.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:710624ab925dc2b05a6229d47f6f0dac1c1155e6ed559be7109f684eba048a48", size = 47627059, upload-time = "2025-10-24T10:03:55.353Z" }, + { url = "https://files.pythonhosted.org/packages/3a/4c/f711acb13075c1391fd54bc17e078587672c575f8de2a6e62509af026dcf/pyarrow-22.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f963ba8c3b0199f9d6b794c90ec77545e05eadc83973897a4523c9e8d84e9340", size = 47947043, upload-time = "2025-10-24T10:04:05.408Z" }, + { url = "https://files.pythonhosted.org/packages/4e/70/1f3180dd7c2eab35c2aca2b29ace6c519f827dcd4cfeb8e0dca41612cf7a/pyarrow-22.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd0d42297ace400d8febe55f13fdf46e86754842b860c978dfec16f081e5c653", size = 50206505, upload-time = "2025-10-24T10:04:15.786Z" }, + { url = "https://files.pythonhosted.org/packages/80/07/fea6578112c8c60ffde55883a571e4c4c6bc7049f119d6b09333b5cc6f73/pyarrow-22.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:00626d9dc0f5ef3a75fe63fd68b9c7c8302d2b5bbc7f74ecaedba83447a24f84", size = 28101641, upload-time = "2025-10-24T10:04:22.57Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b7/18f611a8cdc43417f9394a3ccd3eace2f32183c08b9eddc3d17681819f37/pyarrow-22.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:3e294c5eadfb93d78b0763e859a0c16d4051fc1c5231ae8956d61cb0b5666f5a", size = 34272022, upload-time = "2025-10-24T10:04:28.973Z" }, + { url = "https://files.pythonhosted.org/packages/26/5c/f259e2526c67eb4b9e511741b19870a02363a47a35edbebc55c3178db22d/pyarrow-22.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:69763ab2445f632d90b504a815a2a033f74332997052b721002298ed6de40f2e", size = 35995834, upload-time = "2025-10-24T10:04:35.467Z" }, + { url = "https://files.pythonhosted.org/packages/50/8d/281f0f9b9376d4b7f146913b26fac0aa2829cd1ee7e997f53a27411bbb92/pyarrow-22.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:b41f37cabfe2463232684de44bad753d6be08a7a072f6a83447eeaf0e4d2a215", size = 45030348, upload-time = "2025-10-24T10:04:43.366Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e5/53c0a1c428f0976bf22f513d79c73000926cb00b9c138d8e02daf2102e18/pyarrow-22.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:35ad0f0378c9359b3f297299c3309778bb03b8612f987399a0333a560b43862d", size = 47699480, upload-time = "2025-10-24T10:04:51.486Z" }, + { url = "https://files.pythonhosted.org/packages/95/e1/9dbe4c465c3365959d183e6345d0a8d1dc5b02ca3f8db4760b3bc834cf25/pyarrow-22.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8382ad21458075c2e66a82a29d650f963ce51c7708c7c0ff313a8c206c4fd5e8", size = 48011148, upload-time = "2025-10-24T10:04:59.585Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b4/7caf5d21930061444c3cf4fa7535c82faf5263e22ce43af7c2759ceb5b8b/pyarrow-22.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1a812a5b727bc09c3d7ea072c4eebf657c2f7066155506ba31ebf4792f88f016", size = 50276964, upload-time = "2025-10-24T10:05:08.175Z" }, + { url = "https://files.pythonhosted.org/packages/ae/f3/cec89bd99fa3abf826f14d4e53d3d11340ce6f6af4d14bdcd54cd83b6576/pyarrow-22.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:ec5d40dd494882704fb876c16fa7261a69791e784ae34e6b5992e977bd2e238c", size = 28106517, upload-time = "2025-10-24T10:05:14.314Z" }, + { url = "https://files.pythonhosted.org/packages/af/63/ba23862d69652f85b615ca14ad14f3bcfc5bf1b99ef3f0cd04ff93fdad5a/pyarrow-22.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:bea79263d55c24a32b0d79c00a1c58bb2ee5f0757ed95656b01c0fb310c5af3d", size = 34211578, upload-time = "2025-10-24T10:05:21.583Z" }, + { url = "https://files.pythonhosted.org/packages/b1/d0/f9ad86fe809efd2bcc8be32032fa72e8b0d112b01ae56a053006376c5930/pyarrow-22.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:12fe549c9b10ac98c91cf791d2945e878875d95508e1a5d14091a7aaa66d9cf8", size = 35989906, upload-time = "2025-10-24T10:05:29.485Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a8/f910afcb14630e64d673f15904ec27dd31f1e009b77033c365c84e8c1e1d/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:334f900ff08ce0423407af97e6c26ad5d4e3b0763645559ece6fbf3747d6a8f5", size = 45021677, upload-time = "2025-10-24T10:05:38.274Z" }, + { url = "https://files.pythonhosted.org/packages/13/95/aec81f781c75cd10554dc17a25849c720d54feafb6f7847690478dcf5ef8/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c6c791b09c57ed76a18b03f2631753a4960eefbbca80f846da8baefc6491fcfe", size = 47726315, upload-time = "2025-10-24T10:05:47.314Z" }, + { url = "https://files.pythonhosted.org/packages/bb/d4/74ac9f7a54cfde12ee42734ea25d5a3c9a45db78f9def949307a92720d37/pyarrow-22.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c3200cb41cdbc65156e5f8c908d739b0dfed57e890329413da2748d1a2cd1a4e", size = 47990906, upload-time = "2025-10-24T10:05:58.254Z" }, + { url = "https://files.pythonhosted.org/packages/2e/71/fedf2499bf7a95062eafc989ace56572f3343432570e1c54e6599d5b88da/pyarrow-22.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ac93252226cf288753d8b46280f4edf3433bf9508b6977f8dd8526b521a1bbb9", size = 50306783, upload-time = "2025-10-24T10:06:08.08Z" }, + { url = "https://files.pythonhosted.org/packages/68/ed/b202abd5a5b78f519722f3d29063dda03c114711093c1995a33b8e2e0f4b/pyarrow-22.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:44729980b6c50a5f2bfcc2668d36c569ce17f8b17bccaf470c4313dcbbf13c9d", size = 27972883, upload-time = "2025-10-24T10:06:14.204Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d6/d0fac16a2963002fc22c8fa75180a838737203d558f0ed3b564c4a54eef5/pyarrow-22.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e6e95176209257803a8b3d0394f21604e796dadb643d2f7ca21b66c9c0b30c9a", size = 34204629, upload-time = "2025-10-24T10:06:20.274Z" }, + { url = "https://files.pythonhosted.org/packages/c6/9c/1d6357347fbae062ad3f17082f9ebc29cc733321e892c0d2085f42a2212b/pyarrow-22.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:001ea83a58024818826a9e3f89bf9310a114f7e26dfe404a4c32686f97bd7901", size = 35985783, upload-time = "2025-10-24T10:06:27.301Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c0/782344c2ce58afbea010150df07e3a2f5fdad299cd631697ae7bd3bac6e3/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ce20fe000754f477c8a9125543f1936ea5b8867c5406757c224d745ed033e691", size = 45020999, upload-time = "2025-10-24T10:06:35.387Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e0a15757fccb38c410947df156f9749ae4a3c89b2393741a50521f39a8cf202a", size = 47724601, upload-time = "2025-10-24T10:06:43.551Z" }, + { url = "https://files.pythonhosted.org/packages/69/4d/76e567a4fc2e190ee6072967cb4672b7d9249ac59ae65af2d7e3047afa3b/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cedb9dd9358e4ea1d9bce3665ce0797f6adf97ff142c8e25b46ba9cdd508e9b6", size = 48001050, upload-time = "2025-10-24T10:06:52.284Z" }, + { url = "https://files.pythonhosted.org/packages/01/5e/5653f0535d2a1aef8223cee9d92944cb6bccfee5cf1cd3f462d7cb022790/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:252be4a05f9d9185bb8c18e83764ebcfea7185076c07a7a662253af3a8c07941", size = 50307877, upload-time = "2025-10-24T10:07:02.405Z" }, + { url = "https://files.pythonhosted.org/packages/2d/f8/1d0bd75bf9328a3b826e24a16e5517cd7f9fbf8d34a3184a4566ef5a7f29/pyarrow-22.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:a4893d31e5ef780b6edcaf63122df0f8d321088bb0dee4c8c06eccb1ca28d145", size = 27977099, upload-time = "2025-10-24T10:08:07.259Z" }, + { url = "https://files.pythonhosted.org/packages/90/81/db56870c997805bf2b0f6eeeb2d68458bf4654652dccdcf1bf7a42d80903/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:f7fe3dbe871294ba70d789be16b6e7e52b418311e166e0e3cba9522f0f437fb1", size = 34336685, upload-time = "2025-10-24T10:07:11.47Z" }, + { url = "https://files.pythonhosted.org/packages/1c/98/0727947f199aba8a120f47dfc229eeb05df15bcd7a6f1b669e9f882afc58/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:ba95112d15fd4f1105fb2402c4eab9068f0554435e9b7085924bcfaac2cc306f", size = 36032158, upload-time = "2025-10-24T10:07:18.626Z" }, + { url = "https://files.pythonhosted.org/packages/96/b4/9babdef9c01720a0785945c7cf550e4acd0ebcd7bdd2e6f0aa7981fa85e2/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c064e28361c05d72eed8e744c9605cbd6d2bb7481a511c74071fd9b24bc65d7d", size = 44892060, upload-time = "2025-10-24T10:07:26.002Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ca/2f8804edd6279f78a37062d813de3f16f29183874447ef6d1aadbb4efa0f/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6f9762274496c244d951c819348afbcf212714902742225f649cf02823a6a10f", size = 47504395, upload-time = "2025-10-24T10:07:34.09Z" }, + { url = "https://files.pythonhosted.org/packages/b9/f0/77aa5198fd3943682b2e4faaf179a674f0edea0d55d326d83cb2277d9363/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a9d9ffdc2ab696f6b15b4d1f7cec6658e1d788124418cb30030afbae31c64746", size = 48066216, upload-time = "2025-10-24T10:07:43.528Z" }, + { url = "https://files.pythonhosted.org/packages/79/87/a1937b6e78b2aff18b706d738c9e46ade5bfcf11b294e39c87706a0089ac/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ec1a15968a9d80da01e1d30349b2b0d7cc91e96588ee324ce1b5228175043e95", size = 50288552, upload-time = "2025-10-24T10:07:53.519Z" }, + { url = "https://files.pythonhosted.org/packages/60/ae/b5a5811e11f25788ccfdaa8f26b6791c9807119dffcf80514505527c384c/pyarrow-22.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:bba208d9c7decf9961998edf5c65e3ea4355d5818dd6cd0f6809bec1afb951cc", size = 28262504, upload-time = "2025-10-24T10:08:00.932Z" }, + { url = "https://files.pythonhosted.org/packages/bd/b0/0fa4d28a8edb42b0a7144edd20befd04173ac79819547216f8a9f36f9e50/pyarrow-22.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:9bddc2cade6561f6820d4cd73f99a0243532ad506bc510a75a5a65a522b2d74d", size = 34224062, upload-time = "2025-10-24T10:08:14.101Z" }, + { url = "https://files.pythonhosted.org/packages/0f/a8/7a719076b3c1be0acef56a07220c586f25cd24de0e3f3102b438d18ae5df/pyarrow-22.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e70ff90c64419709d38c8932ea9fe1cc98415c4f87ea8da81719e43f02534bc9", size = 35990057, upload-time = "2025-10-24T10:08:21.842Z" }, + { url = "https://files.pythonhosted.org/packages/89/3c/359ed54c93b47fb6fe30ed16cdf50e3f0e8b9ccfb11b86218c3619ae50a8/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:92843c305330aa94a36e706c16209cd4df274693e777ca47112617db7d0ef3d7", size = 45068002, upload-time = "2025-10-24T10:08:29.034Z" }, + { url = "https://files.pythonhosted.org/packages/55/fc/4945896cc8638536ee787a3bd6ce7cec8ec9acf452d78ec39ab328efa0a1/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:6dda1ddac033d27421c20d7a7943eec60be44e0db4e079f33cc5af3b8280ccde", size = 47737765, upload-time = "2025-10-24T10:08:38.559Z" }, + { url = "https://files.pythonhosted.org/packages/cd/5e/7cb7edeb2abfaa1f79b5d5eb89432356155c8426f75d3753cbcb9592c0fd/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:84378110dd9a6c06323b41b56e129c504d157d1a983ce8f5443761eb5256bafc", size = 48048139, upload-time = "2025-10-24T10:08:46.784Z" }, + { url = "https://files.pythonhosted.org/packages/88/c6/546baa7c48185f5e9d6e59277c4b19f30f48c94d9dd938c2a80d4d6b067c/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:854794239111d2b88b40b6ef92aa478024d1e5074f364033e73e21e3f76b25e0", size = 50314244, upload-time = "2025-10-24T10:08:55.771Z" }, + { url = "https://files.pythonhosted.org/packages/3c/79/755ff2d145aafec8d347bf18f95e4e81c00127f06d080135dfc86aea417c/pyarrow-22.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:b883fe6fd85adad7932b3271c38ac289c65b7337c2c132e9569f9d3940620730", size = 28757501, upload-time = "2025-10-24T10:09:59.891Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d2/237d75ac28ced3147912954e3c1a174df43a95f4f88e467809118a8165e0/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7a820d8ae11facf32585507c11f04e3f38343c1e784c9b5a8b1da5c930547fe2", size = 34355506, upload-time = "2025-10-24T10:09:02.953Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/733dfffe6d3069740f98e57ff81007809067d68626c5faef293434d11bd6/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:c6ec3675d98915bf1ec8b3c7986422682f7232ea76cad276f4c8abd5b7319b70", size = 36047312, upload-time = "2025-10-24T10:09:10.334Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2b/29d6e3782dc1f299727462c1543af357a0f2c1d3c160ce199950d9ca51eb/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3e739edd001b04f654b166204fc7a9de896cf6007eaff33409ee9e50ceaff754", size = 45081609, upload-time = "2025-10-24T10:09:18.61Z" }, + { url = "https://files.pythonhosted.org/packages/8d/42/aa9355ecc05997915af1b7b947a7f66c02dcaa927f3203b87871c114ba10/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:7388ac685cab5b279a41dfe0a6ccd99e4dbf322edfb63e02fc0443bf24134e91", size = 47703663, upload-time = "2025-10-24T10:09:27.369Z" }, + { url = "https://files.pythonhosted.org/packages/ee/62/45abedde480168e83a1de005b7b7043fd553321c1e8c5a9a114425f64842/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f633074f36dbc33d5c05b5dc75371e5660f1dbf9c8b1d95669def05e5425989c", size = 48066543, upload-time = "2025-10-24T10:09:34.908Z" }, + { url = "https://files.pythonhosted.org/packages/84/e9/7878940a5b072e4f3bf998770acafeae13b267f9893af5f6d4ab3904b67e/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4c19236ae2402a8663a2c8f21f1870a03cc57f0bef7e4b6eb3238cc82944de80", size = 50288838, upload-time = "2025-10-24T10:09:44.394Z" }, + { url = "https://files.pythonhosted.org/packages/7b/03/f335d6c52b4a4761bcc83499789a1e2e16d9d201a58c327a9b5cc9a41bd9/pyarrow-22.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0c34fe18094686194f204a3b1787a27456897d8a2d62caf84b61e8dfbc0252ae", size = 29185594, upload-time = "2025-10-24T10:09:53.111Z" }, +] + +[[package]] +name = "pydantic" +version = "2.12.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/1e/4f0a3233767010308f2fd6bd0814597e3f63f1dc98304a9112b8759df4ff/pydantic-2.12.3.tar.gz", hash = "sha256:1da1c82b0fc140bb0103bc1441ffe062154c8d38491189751ee00fd8ca65ce74", size = 819383, upload-time = "2025-10-17T15:04:21.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/6b/83661fa77dcefa195ad5f8cd9af3d1a7450fd57cc883ad04d65446ac2029/pydantic-2.12.3-py3-none-any.whl", hash = "sha256:6986454a854bc3bc6e5443e1369e06a3a456af9d339eda45510f517d9ea5c6bf", size = 462431, upload-time = "2025-10-17T15:04:19.346Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.41.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/18/d0944e8eaaa3efd0a91b0f1fc537d3be55ad35091b6a87638211ba691964/pydantic_core-2.41.4.tar.gz", hash = "sha256:70e47929a9d4a1905a67e4b687d5946026390568a8e952b92824118063cee4d5", size = 457557, upload-time = "2025-10-14T10:23:47.909Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/3d/9b8ca77b0f76fcdbf8bc6b72474e264283f461284ca84ac3fde570c6c49a/pydantic_core-2.41.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2442d9a4d38f3411f22eb9dd0912b7cbf4b7d5b6c92c4173b75d3e1ccd84e36e", size = 2111197, upload-time = "2025-10-14T10:19:43.303Z" }, + { url = "https://files.pythonhosted.org/packages/59/92/b7b0fe6ed4781642232755cb7e56a86e2041e1292f16d9ae410a0ccee5ac/pydantic_core-2.41.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:30a9876226dda131a741afeab2702e2d127209bde3c65a2b8133f428bc5d006b", size = 1917909, upload-time = "2025-10-14T10:19:45.194Z" }, + { url = "https://files.pythonhosted.org/packages/52/8c/3eb872009274ffa4fb6a9585114e161aa1a0915af2896e2d441642929fe4/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d55bbac04711e2980645af68b97d445cdbcce70e5216de444a6c4b6943ebcccd", size = 1969905, upload-time = "2025-10-14T10:19:46.567Z" }, + { url = "https://files.pythonhosted.org/packages/f4/21/35adf4a753bcfaea22d925214a0c5b880792e3244731b3f3e6fec0d124f7/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1d778fb7849a42d0ee5927ab0f7453bf9f85eef8887a546ec87db5ddb178945", size = 2051938, upload-time = "2025-10-14T10:19:48.237Z" }, + { url = "https://files.pythonhosted.org/packages/7d/d0/cdf7d126825e36d6e3f1eccf257da8954452934ede275a8f390eac775e89/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b65077a4693a98b90ec5ad8f203ad65802a1b9b6d4a7e48066925a7e1606706", size = 2250710, upload-time = "2025-10-14T10:19:49.619Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1c/af1e6fd5ea596327308f9c8d1654e1285cc3d8de0d584a3c9d7705bf8a7c/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62637c769dee16eddb7686bf421be48dfc2fae93832c25e25bc7242e698361ba", size = 2367445, upload-time = "2025-10-14T10:19:51.269Z" }, + { url = "https://files.pythonhosted.org/packages/d3/81/8cece29a6ef1b3a92f956ea6da6250d5b2d2e7e4d513dd3b4f0c7a83dfea/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfe3aa529c8f501babf6e502936b9e8d4698502b2cfab41e17a028d91b1ac7b", size = 2072875, upload-time = "2025-10-14T10:19:52.671Z" }, + { url = "https://files.pythonhosted.org/packages/e3/37/a6a579f5fc2cd4d5521284a0ab6a426cc6463a7b3897aeb95b12f1ba607b/pydantic_core-2.41.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca2322da745bf2eeb581fc9ea3bbb31147702163ccbcbf12a3bb630e4bf05e1d", size = 2191329, upload-time = "2025-10-14T10:19:54.214Z" }, + { url = "https://files.pythonhosted.org/packages/ae/03/505020dc5c54ec75ecba9f41119fd1e48f9e41e4629942494c4a8734ded1/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e8cd3577c796be7231dcf80badcf2e0835a46665eaafd8ace124d886bab4d700", size = 2151658, upload-time = "2025-10-14T10:19:55.843Z" }, + { url = "https://files.pythonhosted.org/packages/cb/5d/2c0d09fb53aa03bbd2a214d89ebfa6304be7df9ed86ee3dc7770257f41ee/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:1cae8851e174c83633f0833e90636832857297900133705ee158cf79d40f03e6", size = 2316777, upload-time = "2025-10-14T10:19:57.607Z" }, + { url = "https://files.pythonhosted.org/packages/ea/4b/c2c9c8f5e1f9c864b57d08539d9d3db160e00491c9f5ee90e1bfd905e644/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a26d950449aae348afe1ac8be5525a00ae4235309b729ad4d3399623125b43c9", size = 2320705, upload-time = "2025-10-14T10:19:59.016Z" }, + { url = "https://files.pythonhosted.org/packages/28/c3/a74c1c37f49c0a02c89c7340fafc0ba816b29bd495d1a31ce1bdeacc6085/pydantic_core-2.41.4-cp310-cp310-win32.whl", hash = "sha256:0cf2a1f599efe57fa0051312774280ee0f650e11152325e41dfd3018ef2c1b57", size = 1975464, upload-time = "2025-10-14T10:20:00.581Z" }, + { url = "https://files.pythonhosted.org/packages/d6/23/5dd5c1324ba80303368f7569e2e2e1a721c7d9eb16acb7eb7b7f85cb1be2/pydantic_core-2.41.4-cp310-cp310-win_amd64.whl", hash = "sha256:a8c2e340d7e454dc3340d3d2e8f23558ebe78c98aa8f68851b04dcb7bc37abdc", size = 2024497, upload-time = "2025-10-14T10:20:03.018Z" }, + { url = "https://files.pythonhosted.org/packages/62/4c/f6cbfa1e8efacd00b846764e8484fe173d25b8dab881e277a619177f3384/pydantic_core-2.41.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:28ff11666443a1a8cf2a044d6a545ebffa8382b5f7973f22c36109205e65dc80", size = 2109062, upload-time = "2025-10-14T10:20:04.486Z" }, + { url = "https://files.pythonhosted.org/packages/21/f8/40b72d3868896bfcd410e1bd7e516e762d326201c48e5b4a06446f6cf9e8/pydantic_core-2.41.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:61760c3925d4633290292bad462e0f737b840508b4f722247d8729684f6539ae", size = 1916301, upload-time = "2025-10-14T10:20:06.857Z" }, + { url = "https://files.pythonhosted.org/packages/94/4d/d203dce8bee7faeca791671c88519969d98d3b4e8f225da5b96dad226fc8/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eae547b7315d055b0de2ec3965643b0ab82ad0106a7ffd29615ee9f266a02827", size = 1968728, upload-time = "2025-10-14T10:20:08.353Z" }, + { url = "https://files.pythonhosted.org/packages/65/f5/6a66187775df87c24d526985b3a5d78d861580ca466fbd9d4d0e792fcf6c/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ef9ee5471edd58d1fcce1c80ffc8783a650e3e3a193fe90d52e43bb4d87bff1f", size = 2050238, upload-time = "2025-10-14T10:20:09.766Z" }, + { url = "https://files.pythonhosted.org/packages/5e/b9/78336345de97298cf53236b2f271912ce11f32c1e59de25a374ce12f9cce/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15dd504af121caaf2c95cb90c0ebf71603c53de98305621b94da0f967e572def", size = 2249424, upload-time = "2025-10-14T10:20:11.732Z" }, + { url = "https://files.pythonhosted.org/packages/99/bb/a4584888b70ee594c3d374a71af5075a68654d6c780369df269118af7402/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a926768ea49a8af4d36abd6a8968b8790f7f76dd7cbd5a4c180db2b4ac9a3a2", size = 2366047, upload-time = "2025-10-14T10:20:13.647Z" }, + { url = "https://files.pythonhosted.org/packages/5f/8d/17fc5de9d6418e4d2ae8c675f905cdafdc59d3bf3bf9c946b7ab796a992a/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916b9b7d134bff5440098a4deb80e4cb623e68974a87883299de9124126c2a8", size = 2071163, upload-time = "2025-10-14T10:20:15.307Z" }, + { url = "https://files.pythonhosted.org/packages/54/e7/03d2c5c0b8ed37a4617430db68ec5e7dbba66358b629cd69e11b4d564367/pydantic_core-2.41.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cf90535979089df02e6f17ffd076f07237efa55b7343d98760bde8743c4b265", size = 2190585, upload-time = "2025-10-14T10:20:17.3Z" }, + { url = "https://files.pythonhosted.org/packages/be/fc/15d1c9fe5ad9266a5897d9b932b7f53d7e5cfc800573917a2c5d6eea56ec/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7533c76fa647fade2d7ec75ac5cc079ab3f34879626dae5689b27790a6cf5a5c", size = 2150109, upload-time = "2025-10-14T10:20:19.143Z" }, + { url = "https://files.pythonhosted.org/packages/26/ef/e735dd008808226c83ba56972566138665b71477ad580fa5a21f0851df48/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:37e516bca9264cbf29612539801ca3cd5d1be465f940417b002905e6ed79d38a", size = 2315078, upload-time = "2025-10-14T10:20:20.742Z" }, + { url = "https://files.pythonhosted.org/packages/90/00/806efdcf35ff2ac0f938362350cd9827b8afb116cc814b6b75cf23738c7c/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0c19cb355224037c83642429b8ce261ae108e1c5fbf5c028bac63c77b0f8646e", size = 2318737, upload-time = "2025-10-14T10:20:22.306Z" }, + { url = "https://files.pythonhosted.org/packages/41/7e/6ac90673fe6cb36621a2283552897838c020db343fa86e513d3f563b196f/pydantic_core-2.41.4-cp311-cp311-win32.whl", hash = "sha256:09c2a60e55b357284b5f31f5ab275ba9f7f70b7525e18a132ec1f9160b4f1f03", size = 1974160, upload-time = "2025-10-14T10:20:23.817Z" }, + { url = "https://files.pythonhosted.org/packages/e0/9d/7c5e24ee585c1f8b6356e1d11d40ab807ffde44d2db3b7dfd6d20b09720e/pydantic_core-2.41.4-cp311-cp311-win_amd64.whl", hash = "sha256:711156b6afb5cb1cb7c14a2cc2c4a8b4c717b69046f13c6b332d8a0a8f41ca3e", size = 2021883, upload-time = "2025-10-14T10:20:25.48Z" }, + { url = "https://files.pythonhosted.org/packages/33/90/5c172357460fc28b2871eb4a0fb3843b136b429c6fa827e4b588877bf115/pydantic_core-2.41.4-cp311-cp311-win_arm64.whl", hash = "sha256:6cb9cf7e761f4f8a8589a45e49ed3c0d92d1d696a45a6feaee8c904b26efc2db", size = 1968026, upload-time = "2025-10-14T10:20:27.039Z" }, + { url = "https://files.pythonhosted.org/packages/e9/81/d3b3e95929c4369d30b2a66a91db63c8ed0a98381ae55a45da2cd1cc1288/pydantic_core-2.41.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ab06d77e053d660a6faaf04894446df7b0a7e7aba70c2797465a0a1af00fc887", size = 2099043, upload-time = "2025-10-14T10:20:28.561Z" }, + { url = "https://files.pythonhosted.org/packages/58/da/46fdac49e6717e3a94fc9201403e08d9d61aa7a770fab6190b8740749047/pydantic_core-2.41.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c53ff33e603a9c1179a9364b0a24694f183717b2e0da2b5ad43c316c956901b2", size = 1910699, upload-time = "2025-10-14T10:20:30.217Z" }, + { url = "https://files.pythonhosted.org/packages/1e/63/4d948f1b9dd8e991a5a98b77dd66c74641f5f2e5225fee37994b2e07d391/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:304c54176af2c143bd181d82e77c15c41cbacea8872a2225dd37e6544dce9999", size = 1952121, upload-time = "2025-10-14T10:20:32.246Z" }, + { url = "https://files.pythonhosted.org/packages/b2/a7/e5fc60a6f781fc634ecaa9ecc3c20171d238794cef69ae0af79ac11b89d7/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:025ba34a4cf4fb32f917d5d188ab5e702223d3ba603be4d8aca2f82bede432a4", size = 2041590, upload-time = "2025-10-14T10:20:34.332Z" }, + { url = "https://files.pythonhosted.org/packages/70/69/dce747b1d21d59e85af433428978a1893c6f8a7068fa2bb4a927fba7a5ff/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9f5f30c402ed58f90c70e12eff65547d3ab74685ffe8283c719e6bead8ef53f", size = 2219869, upload-time = "2025-10-14T10:20:35.965Z" }, + { url = "https://files.pythonhosted.org/packages/83/6a/c070e30e295403bf29c4df1cb781317b6a9bac7cd07b8d3acc94d501a63c/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd96e5d15385d301733113bcaa324c8bcf111275b7675a9c6e88bfb19fc05e3b", size = 2345169, upload-time = "2025-10-14T10:20:37.627Z" }, + { url = "https://files.pythonhosted.org/packages/f0/83/06d001f8043c336baea7fd202a9ac7ad71f87e1c55d8112c50b745c40324/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f348cbb44fae6e9653c1055db7e29de67ea6a9ca03a5fa2c2e11a47cff0e47", size = 2070165, upload-time = "2025-10-14T10:20:39.246Z" }, + { url = "https://files.pythonhosted.org/packages/14/0a/e567c2883588dd12bcbc110232d892cf385356f7c8a9910311ac997ab715/pydantic_core-2.41.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec22626a2d14620a83ca583c6f5a4080fa3155282718b6055c2ea48d3ef35970", size = 2189067, upload-time = "2025-10-14T10:20:41.015Z" }, + { url = "https://files.pythonhosted.org/packages/f4/1d/3d9fca34273ba03c9b1c5289f7618bc4bd09c3ad2289b5420481aa051a99/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a95d4590b1f1a43bf33ca6d647b990a88f4a3824a8c4572c708f0b45a5290ed", size = 2132997, upload-time = "2025-10-14T10:20:43.106Z" }, + { url = "https://files.pythonhosted.org/packages/52/70/d702ef7a6cd41a8afc61f3554922b3ed8d19dd54c3bd4bdbfe332e610827/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:f9672ab4d398e1b602feadcffcdd3af44d5f5e6ddc15bc7d15d376d47e8e19f8", size = 2307187, upload-time = "2025-10-14T10:20:44.849Z" }, + { url = "https://files.pythonhosted.org/packages/68/4c/c06be6e27545d08b802127914156f38d10ca287a9e8489342793de8aae3c/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:84d8854db5f55fead3b579f04bda9a36461dab0730c5d570e1526483e7bb8431", size = 2305204, upload-time = "2025-10-14T10:20:46.781Z" }, + { url = "https://files.pythonhosted.org/packages/b0/e5/35ae4919bcd9f18603419e23c5eaf32750224a89d41a8df1a3704b69f77e/pydantic_core-2.41.4-cp312-cp312-win32.whl", hash = "sha256:9be1c01adb2ecc4e464392c36d17f97e9110fbbc906bcbe1c943b5b87a74aabd", size = 1972536, upload-time = "2025-10-14T10:20:48.39Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c2/49c5bb6d2a49eb2ee3647a93e3dae7080c6409a8a7558b075027644e879c/pydantic_core-2.41.4-cp312-cp312-win_amd64.whl", hash = "sha256:d682cf1d22bab22a5be08539dca3d1593488a99998f9f412137bc323179067ff", size = 2031132, upload-time = "2025-10-14T10:20:50.421Z" }, + { url = "https://files.pythonhosted.org/packages/06/23/936343dbcba6eec93f73e95eb346810fc732f71ba27967b287b66f7b7097/pydantic_core-2.41.4-cp312-cp312-win_arm64.whl", hash = "sha256:833eebfd75a26d17470b58768c1834dfc90141b7afc6eb0429c21fc5a21dcfb8", size = 1969483, upload-time = "2025-10-14T10:20:52.35Z" }, + { url = "https://files.pythonhosted.org/packages/13/d0/c20adabd181a029a970738dfe23710b52a31f1258f591874fcdec7359845/pydantic_core-2.41.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:85e050ad9e5f6fe1004eec65c914332e52f429bc0ae12d6fa2092407a462c746", size = 2105688, upload-time = "2025-10-14T10:20:54.448Z" }, + { url = "https://files.pythonhosted.org/packages/00/b6/0ce5c03cec5ae94cca220dfecddc453c077d71363b98a4bbdb3c0b22c783/pydantic_core-2.41.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7393f1d64792763a48924ba31d1e44c2cfbc05e3b1c2c9abb4ceeadd912cced", size = 1910807, upload-time = "2025-10-14T10:20:56.115Z" }, + { url = "https://files.pythonhosted.org/packages/68/3e/800d3d02c8beb0b5c069c870cbb83799d085debf43499c897bb4b4aaff0d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94dab0940b0d1fb28bcab847adf887c66a27a40291eedf0b473be58761c9799a", size = 1956669, upload-time = "2025-10-14T10:20:57.874Z" }, + { url = "https://files.pythonhosted.org/packages/60/a4/24271cc71a17f64589be49ab8bd0751f6a0a03046c690df60989f2f95c2c/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de7c42f897e689ee6f9e93c4bec72b99ae3b32a2ade1c7e4798e690ff5246e02", size = 2051629, upload-time = "2025-10-14T10:21:00.006Z" }, + { url = "https://files.pythonhosted.org/packages/68/de/45af3ca2f175d91b96bfb62e1f2d2f1f9f3b14a734afe0bfeff079f78181/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:664b3199193262277b8b3cd1e754fb07f2c6023289c815a1e1e8fb415cb247b1", size = 2224049, upload-time = "2025-10-14T10:21:01.801Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/ae4e1ff84672bf869d0a77af24fd78387850e9497753c432875066b5d622/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95b253b88f7d308b1c0b417c4624f44553ba4762816f94e6986819b9c273fb2", size = 2342409, upload-time = "2025-10-14T10:21:03.556Z" }, + { url = "https://files.pythonhosted.org/packages/18/62/273dd70b0026a085c7b74b000394e1ef95719ea579c76ea2f0cc8893736d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1351f5bbdbbabc689727cb91649a00cb9ee7203e0a6e54e9f5ba9e22e384b84", size = 2069635, upload-time = "2025-10-14T10:21:05.385Z" }, + { url = "https://files.pythonhosted.org/packages/30/03/cf485fff699b4cdaea469bc481719d3e49f023241b4abb656f8d422189fc/pydantic_core-2.41.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1affa4798520b148d7182da0615d648e752de4ab1a9566b7471bc803d88a062d", size = 2194284, upload-time = "2025-10-14T10:21:07.122Z" }, + { url = "https://files.pythonhosted.org/packages/f9/7e/c8e713db32405dfd97211f2fc0a15d6bf8adb7640f3d18544c1f39526619/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7b74e18052fea4aa8dea2fb7dbc23d15439695da6cbe6cfc1b694af1115df09d", size = 2137566, upload-time = "2025-10-14T10:21:08.981Z" }, + { url = "https://files.pythonhosted.org/packages/04/f7/db71fd4cdccc8b75990f79ccafbbd66757e19f6d5ee724a6252414483fb4/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:285b643d75c0e30abda9dc1077395624f314a37e3c09ca402d4015ef5979f1a2", size = 2316809, upload-time = "2025-10-14T10:21:10.805Z" }, + { url = "https://files.pythonhosted.org/packages/76/63/a54973ddb945f1bca56742b48b144d85c9fc22f819ddeb9f861c249d5464/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f52679ff4218d713b3b33f88c89ccbf3a5c2c12ba665fb80ccc4192b4608dbab", size = 2311119, upload-time = "2025-10-14T10:21:12.583Z" }, + { url = "https://files.pythonhosted.org/packages/f8/03/5d12891e93c19218af74843a27e32b94922195ded2386f7b55382f904d2f/pydantic_core-2.41.4-cp313-cp313-win32.whl", hash = "sha256:ecde6dedd6fff127c273c76821bb754d793be1024bc33314a120f83a3c69460c", size = 1981398, upload-time = "2025-10-14T10:21:14.584Z" }, + { url = "https://files.pythonhosted.org/packages/be/d8/fd0de71f39db91135b7a26996160de71c073d8635edfce8b3c3681be0d6d/pydantic_core-2.41.4-cp313-cp313-win_amd64.whl", hash = "sha256:d081a1f3800f05409ed868ebb2d74ac39dd0c1ff6c035b5162356d76030736d4", size = 2030735, upload-time = "2025-10-14T10:21:16.432Z" }, + { url = "https://files.pythonhosted.org/packages/72/86/c99921c1cf6650023c08bfab6fe2d7057a5142628ef7ccfa9921f2dda1d5/pydantic_core-2.41.4-cp313-cp313-win_arm64.whl", hash = "sha256:f8e49c9c364a7edcbe2a310f12733aad95b022495ef2a8d653f645e5d20c1564", size = 1973209, upload-time = "2025-10-14T10:21:18.213Z" }, + { url = "https://files.pythonhosted.org/packages/36/0d/b5706cacb70a8414396efdda3d72ae0542e050b591119e458e2490baf035/pydantic_core-2.41.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ed97fd56a561f5eb5706cebe94f1ad7c13b84d98312a05546f2ad036bafe87f4", size = 1877324, upload-time = "2025-10-14T10:21:20.363Z" }, + { url = "https://files.pythonhosted.org/packages/de/2d/cba1fa02cfdea72dfb3a9babb067c83b9dff0bbcb198368e000a6b756ea7/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a870c307bf1ee91fc58a9a61338ff780d01bfae45922624816878dce784095d2", size = 1884515, upload-time = "2025-10-14T10:21:22.339Z" }, + { url = "https://files.pythonhosted.org/packages/07/ea/3df927c4384ed9b503c9cc2d076cf983b4f2adb0c754578dfb1245c51e46/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25e97bc1f5f8f7985bdc2335ef9e73843bb561eb1fa6831fdfc295c1c2061cf", size = 2042819, upload-time = "2025-10-14T10:21:26.683Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ee/df8e871f07074250270a3b1b82aad4cd0026b588acd5d7d3eb2fcb1471a3/pydantic_core-2.41.4-cp313-cp313t-win_amd64.whl", hash = "sha256:d405d14bea042f166512add3091c1af40437c2e7f86988f3915fabd27b1e9cd2", size = 1995866, upload-time = "2025-10-14T10:21:28.951Z" }, + { url = "https://files.pythonhosted.org/packages/fc/de/b20f4ab954d6d399499c33ec4fafc46d9551e11dc1858fb7f5dca0748ceb/pydantic_core-2.41.4-cp313-cp313t-win_arm64.whl", hash = "sha256:19f3684868309db5263a11bace3c45d93f6f24afa2ffe75a647583df22a2ff89", size = 1970034, upload-time = "2025-10-14T10:21:30.869Z" }, + { url = "https://files.pythonhosted.org/packages/54/28/d3325da57d413b9819365546eb9a6e8b7cbd9373d9380efd5f74326143e6/pydantic_core-2.41.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e9205d97ed08a82ebb9a307e92914bb30e18cdf6f6b12ca4bedadb1588a0bfe1", size = 2102022, upload-time = "2025-10-14T10:21:32.809Z" }, + { url = "https://files.pythonhosted.org/packages/9e/24/b58a1bc0d834bf1acc4361e61233ee217169a42efbdc15a60296e13ce438/pydantic_core-2.41.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:82df1f432b37d832709fbcc0e24394bba04a01b6ecf1ee87578145c19cde12ac", size = 1905495, upload-time = "2025-10-14T10:21:34.812Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a4/71f759cc41b7043e8ecdaab81b985a9b6cad7cec077e0b92cff8b71ecf6b/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3b4cc4539e055cfa39a3763c939f9d409eb40e85813257dcd761985a108554", size = 1956131, upload-time = "2025-10-14T10:21:36.924Z" }, + { url = "https://files.pythonhosted.org/packages/b0/64/1e79ac7aa51f1eec7c4cda8cbe456d5d09f05fdd68b32776d72168d54275/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1eb1754fce47c63d2ff57fdb88c351a6c0150995890088b33767a10218eaa4e", size = 2052236, upload-time = "2025-10-14T10:21:38.927Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e3/a3ffc363bd4287b80f1d43dc1c28ba64831f8dfc237d6fec8f2661138d48/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6ab5ab30ef325b443f379ddb575a34969c333004fca5a1daa0133a6ffaad616", size = 2223573, upload-time = "2025-10-14T10:21:41.574Z" }, + { url = "https://files.pythonhosted.org/packages/28/27/78814089b4d2e684a9088ede3790763c64693c3d1408ddc0a248bc789126/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31a41030b1d9ca497634092b46481b937ff9397a86f9f51bd41c4767b6fc04af", size = 2342467, upload-time = "2025-10-14T10:21:44.018Z" }, + { url = "https://files.pythonhosted.org/packages/92/97/4de0e2a1159cb85ad737e03306717637842c88c7fd6d97973172fb183149/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a44ac1738591472c3d020f61c6df1e4015180d6262ebd39bf2aeb52571b60f12", size = 2063754, upload-time = "2025-10-14T10:21:46.466Z" }, + { url = "https://files.pythonhosted.org/packages/0f/50/8cb90ce4b9efcf7ae78130afeb99fd1c86125ccdf9906ef64b9d42f37c25/pydantic_core-2.41.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d72f2b5e6e82ab8f94ea7d0d42f83c487dc159c5240d8f83beae684472864e2d", size = 2196754, upload-time = "2025-10-14T10:21:48.486Z" }, + { url = "https://files.pythonhosted.org/packages/34/3b/ccdc77af9cd5082723574a1cc1bcae7a6acacc829d7c0a06201f7886a109/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c4d1e854aaf044487d31143f541f7aafe7b482ae72a022c664b2de2e466ed0ad", size = 2137115, upload-time = "2025-10-14T10:21:50.63Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ba/e7c7a02651a8f7c52dc2cff2b64a30c313e3b57c7d93703cecea76c09b71/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b568af94267729d76e6ee5ececda4e283d07bbb28e8148bb17adad93d025d25a", size = 2317400, upload-time = "2025-10-14T10:21:52.959Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ba/6c533a4ee8aec6b812c643c49bb3bd88d3f01e3cebe451bb85512d37f00f/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6d55fb8b1e8929b341cc313a81a26e0d48aa3b519c1dbaadec3a6a2b4fcad025", size = 2312070, upload-time = "2025-10-14T10:21:55.419Z" }, + { url = "https://files.pythonhosted.org/packages/22/ae/f10524fcc0ab8d7f96cf9a74c880243576fd3e72bd8ce4f81e43d22bcab7/pydantic_core-2.41.4-cp314-cp314-win32.whl", hash = "sha256:5b66584e549e2e32a1398df11da2e0a7eff45d5c2d9db9d5667c5e6ac764d77e", size = 1982277, upload-time = "2025-10-14T10:21:57.474Z" }, + { url = "https://files.pythonhosted.org/packages/b4/dc/e5aa27aea1ad4638f0c3fb41132f7eb583bd7420ee63204e2d4333a3bbf9/pydantic_core-2.41.4-cp314-cp314-win_amd64.whl", hash = "sha256:557a0aab88664cc552285316809cab897716a372afaf8efdbef756f8b890e894", size = 2024608, upload-time = "2025-10-14T10:21:59.557Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/51d89cc2612bd147198e120a13f150afbf0bcb4615cddb049ab10b81b79e/pydantic_core-2.41.4-cp314-cp314-win_arm64.whl", hash = "sha256:3f1ea6f48a045745d0d9f325989d8abd3f1eaf47dd00485912d1a3a63c623a8d", size = 1967614, upload-time = "2025-10-14T10:22:01.847Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c2/472f2e31b95eff099961fa050c376ab7156a81da194f9edb9f710f68787b/pydantic_core-2.41.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6c1fe4c5404c448b13188dd8bd2ebc2bdd7e6727fa61ff481bcc2cca894018da", size = 1876904, upload-time = "2025-10-14T10:22:04.062Z" }, + { url = "https://files.pythonhosted.org/packages/4a/07/ea8eeb91173807ecdae4f4a5f4b150a520085b35454350fc219ba79e66a3/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:523e7da4d43b113bf8e7b49fa4ec0c35bf4fe66b2230bfc5c13cc498f12c6c3e", size = 1882538, upload-time = "2025-10-14T10:22:06.39Z" }, + { url = "https://files.pythonhosted.org/packages/1e/29/b53a9ca6cd366bfc928823679c6a76c7a4c69f8201c0ba7903ad18ebae2f/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5729225de81fb65b70fdb1907fcf08c75d498f4a6f15af005aabb1fdadc19dfa", size = 2041183, upload-time = "2025-10-14T10:22:08.812Z" }, + { url = "https://files.pythonhosted.org/packages/c7/3d/f8c1a371ceebcaf94d6dd2d77c6cf4b1c078e13a5837aee83f760b4f7cfd/pydantic_core-2.41.4-cp314-cp314t-win_amd64.whl", hash = "sha256:de2cfbb09e88f0f795fd90cf955858fc2c691df65b1f21f0aa00b99f3fbc661d", size = 1993542, upload-time = "2025-10-14T10:22:11.332Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ac/9fc61b4f9d079482a290afe8d206b8f490e9fd32d4fc03ed4fc698214e01/pydantic_core-2.41.4-cp314-cp314t-win_arm64.whl", hash = "sha256:d34f950ae05a83e0ede899c595f312ca976023ea1db100cd5aa188f7005e3ab0", size = 1973897, upload-time = "2025-10-14T10:22:13.444Z" }, + { url = "https://files.pythonhosted.org/packages/b0/12/5ba58daa7f453454464f92b3ca7b9d7c657d8641c48e370c3ebc9a82dd78/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:a1b2cfec3879afb742a7b0bcfa53e4f22ba96571c9e54d6a3afe1052d17d843b", size = 2122139, upload-time = "2025-10-14T10:22:47.288Z" }, + { url = "https://files.pythonhosted.org/packages/21/fb/6860126a77725c3108baecd10fd3d75fec25191d6381b6eb2ac660228eac/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:d175600d975b7c244af6eb9c9041f10059f20b8bbffec9e33fdd5ee3f67cdc42", size = 1936674, upload-time = "2025-10-14T10:22:49.555Z" }, + { url = "https://files.pythonhosted.org/packages/de/be/57dcaa3ed595d81f8757e2b44a38240ac5d37628bce25fb20d02c7018776/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f184d657fa4947ae5ec9c47bd7e917730fa1cbb78195037e32dcbab50aca5ee", size = 1956398, upload-time = "2025-10-14T10:22:52.19Z" }, + { url = "https://files.pythonhosted.org/packages/2f/1d/679a344fadb9695f1a6a294d739fbd21d71fa023286daeea8c0ed49e7c2b/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ed810568aeffed3edc78910af32af911c835cc39ebbfacd1f0ab5dd53028e5c", size = 2138674, upload-time = "2025-10-14T10:22:54.499Z" }, + { url = "https://files.pythonhosted.org/packages/c4/48/ae937e5a831b7c0dc646b2ef788c27cd003894882415300ed21927c21efa/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:4f5d640aeebb438517150fdeec097739614421900e4a08db4a3ef38898798537", size = 2112087, upload-time = "2025-10-14T10:22:56.818Z" }, + { url = "https://files.pythonhosted.org/packages/5e/db/6db8073e3d32dae017da7e0d16a9ecb897d0a4d92e00634916e486097961/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:4a9ab037b71927babc6d9e7fc01aea9e66dc2a4a34dff06ef0724a4049629f94", size = 1920387, upload-time = "2025-10-14T10:22:59.342Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c1/dd3542d072fcc336030d66834872f0328727e3b8de289c662faa04aa270e/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4dab9484ec605c3016df9ad4fd4f9a390bc5d816a3b10c6550f8424bb80b18c", size = 1951495, upload-time = "2025-10-14T10:23:02.089Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c6/db8d13a1f8ab3f1eb08c88bd00fd62d44311e3456d1e85c0e59e0a0376e7/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8a5028425820731d8c6c098ab642d7b8b999758e24acae03ed38a66eca8335", size = 2139008, upload-time = "2025-10-14T10:23:04.539Z" }, + { url = "https://files.pythonhosted.org/packages/5d/d4/912e976a2dd0b49f31c98a060ca90b353f3b73ee3ea2fd0030412f6ac5ec/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e5ab4fc177dd41536b3c32b2ea11380dd3d4619a385860621478ac2d25ceb00", size = 2106739, upload-time = "2025-10-14T10:23:06.934Z" }, + { url = "https://files.pythonhosted.org/packages/71/f0/66ec5a626c81eba326072d6ee2b127f8c139543f1bf609b4842978d37833/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3d88d0054d3fa11ce936184896bed3c1c5441d6fa483b498fac6a5d0dd6f64a9", size = 1932549, upload-time = "2025-10-14T10:23:09.24Z" }, + { url = "https://files.pythonhosted.org/packages/c4/af/625626278ca801ea0a658c2dcf290dc9f21bb383098e99e7c6a029fccfc0/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2a054a8725f05b4b6503357e0ac1c4e8234ad3b0c2ac130d6ffc66f0e170e2", size = 2135093, upload-time = "2025-10-14T10:23:11.626Z" }, + { url = "https://files.pythonhosted.org/packages/20/f6/2fba049f54e0f4975fef66be654c597a1d005320fa141863699180c7697d/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0d9db5a161c99375a0c68c058e227bee1d89303300802601d76a3d01f74e258", size = 2187971, upload-time = "2025-10-14T10:23:14.437Z" }, + { url = "https://files.pythonhosted.org/packages/0e/80/65ab839a2dfcd3b949202f9d920c34f9de5a537c3646662bdf2f7d999680/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6273ea2c8ffdac7b7fda2653c49682db815aebf4a89243a6feccf5e36c18c347", size = 2147939, upload-time = "2025-10-14T10:23:16.831Z" }, + { url = "https://files.pythonhosted.org/packages/44/58/627565d3d182ce6dfda18b8e1c841eede3629d59c9d7cbc1e12a03aeb328/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:4c973add636efc61de22530b2ef83a65f39b6d6f656df97f678720e20de26caa", size = 2311400, upload-time = "2025-10-14T10:23:19.234Z" }, + { url = "https://files.pythonhosted.org/packages/24/06/8a84711162ad5a5f19a88cead37cca81b4b1f294f46260ef7334ae4f24d3/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b69d1973354758007f46cf2d44a4f3d0933f10b6dc9bf15cf1356e037f6f731a", size = 2316840, upload-time = "2025-10-14T10:23:21.738Z" }, + { url = "https://files.pythonhosted.org/packages/aa/8b/b7bb512a4682a2f7fbfae152a755d37351743900226d29bd953aaf870eaa/pydantic_core-2.41.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3619320641fd212aaf5997b6ca505e97540b7e16418f4a241f44cdf108ffb50d", size = 2149135, upload-time = "2025-10-14T10:23:24.379Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7d/138e902ed6399b866f7cfe4435d22445e16fff888a1c00560d9dc79a780f/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:491535d45cd7ad7e4a2af4a5169b0d07bebf1adfd164b0368da8aa41e19907a5", size = 2104721, upload-time = "2025-10-14T10:23:26.906Z" }, + { url = "https://files.pythonhosted.org/packages/47/13/0525623cf94627f7b53b4c2034c81edc8491cbfc7c28d5447fa318791479/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:54d86c0cada6aba4ec4c047d0e348cbad7063b87ae0f005d9f8c9ad04d4a92a2", size = 1931608, upload-time = "2025-10-14T10:23:29.306Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f9/744bc98137d6ef0a233f808bfc9b18cf94624bf30836a18d3b05d08bf418/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca1124aced216b2500dc2609eade086d718e8249cb9696660ab447d50a758bd", size = 2132986, upload-time = "2025-10-14T10:23:32.057Z" }, + { url = "https://files.pythonhosted.org/packages/17/c8/629e88920171173f6049386cc71f893dff03209a9ef32b4d2f7e7c264bcf/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c9024169becccf0cb470ada03ee578d7348c119a0d42af3dcf9eda96e3a247c", size = 2187516, upload-time = "2025-10-14T10:23:34.871Z" }, + { url = "https://files.pythonhosted.org/packages/2e/0f/4f2734688d98488782218ca61bcc118329bf5de05bb7fe3adc7dd79b0b86/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:26895a4268ae5a2849269f4991cdc97236e4b9c010e51137becf25182daac405", size = 2146146, upload-time = "2025-10-14T10:23:37.342Z" }, + { url = "https://files.pythonhosted.org/packages/ed/f2/ab385dbd94a052c62224b99cf99002eee99dbec40e10006c78575aead256/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:ca4df25762cf71308c446e33c9b1fdca2923a3f13de616e2a949f38bf21ff5a8", size = 2311296, upload-time = "2025-10-14T10:23:40.145Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8e/e4f12afe1beeb9823bba5375f8f258df0cc61b056b0195fb1cf9f62a1a58/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:5a28fcedd762349519276c36634e71853b4541079cab4acaaac60c4421827308", size = 2315386, upload-time = "2025-10-14T10:23:42.624Z" }, + { url = "https://files.pythonhosted.org/packages/48/f7/925f65d930802e3ea2eb4d5afa4cb8730c8dc0d2cb89a59dc4ed2fcb2d74/pydantic_core-2.41.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c173ddcd86afd2535e2b695217e82191580663a1d1928239f877f5a1649ef39f", size = 2147775, upload-time = "2025-10-14T10:23:45.406Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyparsing" +version = "3.2.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/a5/181488fc2b9d093e3972d2a472855aae8a03f000592dbfce716a512b3359/pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6", size = 1099274, upload-time = "2025-09-21T04:11:06.277Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e", size = 113890, upload-time = "2025-09-21T04:11:04.117Z" }, +] + +[[package]] +name = "pytest" +version = "9.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "pytz" +version = "2025.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "regex" +version = "2025.10.23" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/c8/1d2160d36b11fbe0a61acb7c3c81ab032d9ec8ad888ac9e0a61b85ab99dd/regex-2025.10.23.tar.gz", hash = "sha256:8cbaf8ceb88f96ae2356d01b9adf5e6306fa42fa6f7eab6b97794e37c959ac26", size = 401266, upload-time = "2025-10-21T15:58:20.23Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/11/849d5d23633a77047465eaae4cc0cbf24ded7aa496c02e8b9710e28b1687/regex-2025.10.23-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:17bbcde374bef1c5fad9b131f0e28a6a24856dd90368d8c0201e2b5a69533daa", size = 487957, upload-time = "2025-10-21T15:54:26.151Z" }, + { url = "https://files.pythonhosted.org/packages/87/12/5985386e7e3200a0d6a6417026d2c758d783a932428a5efc0a42ca1ddf74/regex-2025.10.23-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4e10434279cc8567f99ca6e018e9025d14f2fded2a603380b6be2090f476426", size = 290419, upload-time = "2025-10-21T15:54:28.804Z" }, + { url = "https://files.pythonhosted.org/packages/67/cf/a8615923f962f8fdc41a3a6093a48726955e8b1993f4614b26a41d249f9b/regex-2025.10.23-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c9bb421cbe7012c744a5a56cf4d6c80829c72edb1a2991677299c988d6339c8", size = 288285, upload-time = "2025-10-21T15:54:30.47Z" }, + { url = "https://files.pythonhosted.org/packages/4e/3d/6a3a1e12c86354cd0b3cbf8c3dd6acbe853609ee3b39d47ecd3ce95caf84/regex-2025.10.23-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:275cd1c2ed8c4a78ebfa489618d7aee762e8b4732da73573c3e38236ec5f65de", size = 781458, upload-time = "2025-10-21T15:54:31.978Z" }, + { url = "https://files.pythonhosted.org/packages/46/47/76a8da004489f2700361754859e373b87a53d043de8c47f4d1583fd39d78/regex-2025.10.23-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7b426ae7952f3dc1e73a86056d520bd4e5f021397484a6835902fc5648bcacce", size = 850605, upload-time = "2025-10-21T15:54:33.753Z" }, + { url = "https://files.pythonhosted.org/packages/67/05/fa886461f97d45a6f4b209699cb994dc6d6212d6e219d29444dac5005775/regex-2025.10.23-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c5cdaf5b6d37c7da1967dbe729d819461aab6a98a072feef65bbcff0a6e60649", size = 898563, upload-time = "2025-10-21T15:54:35.431Z" }, + { url = "https://files.pythonhosted.org/packages/2d/db/3ddd8d01455f23cabad7499f4199de0df92f5e96d39633203ff9d0b592dc/regex-2025.10.23-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3bfeff0b08f296ab28b4332a7e03ca31c437ee78b541ebc874bbf540e5932f8d", size = 791535, upload-time = "2025-10-21T15:54:37.269Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ae/0fa5cbf41ca92b6ec3370222fcb6c68b240d68ab10e803d086c03a19fd9e/regex-2025.10.23-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5f97236a67307b775f30a74ef722b64b38b7ab7ba3bb4a2508518a5de545459c", size = 782461, upload-time = "2025-10-21T15:54:39.187Z" }, + { url = "https://files.pythonhosted.org/packages/d4/23/70af22a016df11af4def27870eb175c2c7235b72d411ecf75a4b4a422cb6/regex-2025.10.23-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:be19e7de499940cd72475fb8e46ab2ecb1cf5906bebdd18a89f9329afb1df82f", size = 774583, upload-time = "2025-10-21T15:54:41.018Z" }, + { url = "https://files.pythonhosted.org/packages/7a/ee/a54a6851f6905f33d3c4ed64e8737b1d85ed01b5724712530ddc0f9abdb1/regex-2025.10.23-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:883df76ee42d9ecb82b37ff8d01caea5895b3f49630a64d21111078bbf8ef64c", size = 845649, upload-time = "2025-10-21T15:54:42.615Z" }, + { url = "https://files.pythonhosted.org/packages/80/7d/c3ec1cae14e01fab00e38c41ed35f47a853359e95e9c023e9a4381bb122c/regex-2025.10.23-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2e9117d1d35fc2addae6281019ecc70dc21c30014b0004f657558b91c6a8f1a7", size = 836037, upload-time = "2025-10-21T15:54:44.63Z" }, + { url = "https://files.pythonhosted.org/packages/15/ae/45771140dd43c4d67c87b54d3728078ed6a96599d9fc7ba6825086236782/regex-2025.10.23-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0ff1307f531a5d8cf5c20ea517254551ff0a8dc722193aab66c656c5a900ea68", size = 779705, upload-time = "2025-10-21T15:54:46.08Z" }, + { url = "https://files.pythonhosted.org/packages/b8/95/074e2581760eafce7c816a352b7d3a322536e5b68c346d1a8bacd895545c/regex-2025.10.23-cp310-cp310-win32.whl", hash = "sha256:7888475787cbfee4a7cd32998eeffe9a28129fa44ae0f691b96cb3939183ef41", size = 265663, upload-time = "2025-10-21T15:54:47.854Z" }, + { url = "https://files.pythonhosted.org/packages/f7/c7/a25f56a718847e34d3f1608c72eadeb67653bff1a0411da023dd8f4c647b/regex-2025.10.23-cp310-cp310-win_amd64.whl", hash = "sha256:ec41a905908496ce4906dab20fb103c814558db1d69afc12c2f384549c17936a", size = 277587, upload-time = "2025-10-21T15:54:49.571Z" }, + { url = "https://files.pythonhosted.org/packages/d3/e5/63eb17c6b5deaefd93c2bbb1feae7c0a8d2157da25883a6ca2569cf7a663/regex-2025.10.23-cp310-cp310-win_arm64.whl", hash = "sha256:b2b7f19a764d5e966d5a62bf2c28a8b4093cc864c6734510bdb4aeb840aec5e6", size = 269979, upload-time = "2025-10-21T15:54:51.375Z" }, + { url = "https://files.pythonhosted.org/packages/82/e5/74b7cd5cd76b4171f9793042045bb1726f7856dd56e582fc3e058a7a8a5e/regex-2025.10.23-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6c531155bf9179345e85032052a1e5fe1a696a6abf9cea54b97e8baefff970fd", size = 487960, upload-time = "2025-10-21T15:54:53.253Z" }, + { url = "https://files.pythonhosted.org/packages/b9/08/854fa4b3b20471d1df1c71e831b6a1aa480281e37791e52a2df9641ec5c6/regex-2025.10.23-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:912e9df4e89d383681268d38ad8f5780d7cccd94ba0e9aa09ca7ab7ab4f8e7eb", size = 290425, upload-time = "2025-10-21T15:54:55.21Z" }, + { url = "https://files.pythonhosted.org/packages/ab/d3/6272b1dd3ca1271661e168762b234ad3e00dbdf4ef0c7b9b72d2d159efa7/regex-2025.10.23-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f375c61bfc3138b13e762fe0ae76e3bdca92497816936534a0177201666f44f", size = 288278, upload-time = "2025-10-21T15:54:56.862Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/c7b365dd9d9bc0a36e018cb96f2ffb60d2ba8deb589a712b437f67de2920/regex-2025.10.23-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e248cc9446081119128ed002a3801f8031e0c219b5d3c64d3cc627da29ac0a33", size = 793289, upload-time = "2025-10-21T15:54:58.352Z" }, + { url = "https://files.pythonhosted.org/packages/d4/fb/b8fbe9aa16cf0c21f45ec5a6c74b4cecbf1a1c0deb7089d4a6f83a9c1caa/regex-2025.10.23-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b52bf9282fdf401e4f4e721f0f61fc4b159b1307244517789702407dd74e38ca", size = 860321, upload-time = "2025-10-21T15:54:59.813Z" }, + { url = "https://files.pythonhosted.org/packages/b0/81/bf41405c772324926a9bd8a640dedaa42da0e929241834dfce0733070437/regex-2025.10.23-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c084889ab2c59765a0d5ac602fd1c3c244f9b3fcc9a65fdc7ba6b74c5287490", size = 907011, upload-time = "2025-10-21T15:55:01.968Z" }, + { url = "https://files.pythonhosted.org/packages/a4/fb/5ad6a8b92d3f88f3797b51bb4ef47499acc2d0b53d2fbe4487a892f37a73/regex-2025.10.23-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d80e8eb79009bdb0936658c44ca06e2fbbca67792013e3818eea3f5f228971c2", size = 800312, upload-time = "2025-10-21T15:55:04.15Z" }, + { url = "https://files.pythonhosted.org/packages/42/48/b4efba0168a2b57f944205d823f8e8a3a1ae6211a34508f014ec2c712f4f/regex-2025.10.23-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b6f259118ba87b814a8ec475380aee5f5ae97a75852a3507cf31d055b01b5b40", size = 782839, upload-time = "2025-10-21T15:55:05.641Z" }, + { url = "https://files.pythonhosted.org/packages/13/2a/c9efb4c6c535b0559c1fa8e431e0574d229707c9ca718600366fcfef6801/regex-2025.10.23-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9b8c72a242683dcc72d37595c4f1278dfd7642b769e46700a8df11eab19dfd82", size = 854270, upload-time = "2025-10-21T15:55:07.27Z" }, + { url = "https://files.pythonhosted.org/packages/34/2d/68eecc1bdaee020e8ba549502291c9450d90d8590d0552247c9b543ebf7b/regex-2025.10.23-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a8d7b7a0a3df9952f9965342159e0c1f05384c0f056a47ce8b61034f8cecbe83", size = 845771, upload-time = "2025-10-21T15:55:09.477Z" }, + { url = "https://files.pythonhosted.org/packages/a5/cd/a1ae499cf9b87afb47a67316bbf1037a7c681ffe447c510ed98c0aa2c01c/regex-2025.10.23-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:413bfea20a484c524858125e92b9ce6ffdd0a4b97d4ff96b5859aa119b0f1bdd", size = 788778, upload-time = "2025-10-21T15:55:11.396Z" }, + { url = "https://files.pythonhosted.org/packages/38/f9/70765e63f5ea7d43b2b6cd4ee9d3323f16267e530fb2a420d92d991cf0fc/regex-2025.10.23-cp311-cp311-win32.whl", hash = "sha256:f76deef1f1019a17dad98f408b8f7afc4bd007cbe835ae77b737e8c7f19ae575", size = 265666, upload-time = "2025-10-21T15:55:13.306Z" }, + { url = "https://files.pythonhosted.org/packages/9c/1a/18e9476ee1b63aaec3844d8e1cb21842dc19272c7e86d879bfc0dcc60db3/regex-2025.10.23-cp311-cp311-win_amd64.whl", hash = "sha256:59bba9f7125536f23fdab5deeea08da0c287a64c1d3acc1c7e99515809824de8", size = 277600, upload-time = "2025-10-21T15:55:15.087Z" }, + { url = "https://files.pythonhosted.org/packages/1d/1b/c019167b1f7a8ec77251457e3ff0339ed74ca8bce1ea13138dc98309c923/regex-2025.10.23-cp311-cp311-win_arm64.whl", hash = "sha256:b103a752b6f1632ca420225718d6ed83f6a6ced3016dd0a4ab9a6825312de566", size = 269974, upload-time = "2025-10-21T15:55:16.841Z" }, + { url = "https://files.pythonhosted.org/packages/f6/57/eeb274d83ab189d02d778851b1ac478477522a92b52edfa6e2ae9ff84679/regex-2025.10.23-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7a44d9c00f7a0a02d3b777429281376370f3d13d2c75ae74eb94e11ebcf4a7fc", size = 489187, upload-time = "2025-10-21T15:55:18.322Z" }, + { url = "https://files.pythonhosted.org/packages/55/5c/7dad43a9b6ea88bf77e0b8b7729a4c36978e1043165034212fd2702880c6/regex-2025.10.23-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b83601f84fde939ae3478bb32a3aef36f61b58c3208d825c7e8ce1a735f143f2", size = 291122, upload-time = "2025-10-21T15:55:20.2Z" }, + { url = "https://files.pythonhosted.org/packages/66/21/38b71e6f2818f0f4b281c8fba8d9d57cfca7b032a648fa59696e0a54376a/regex-2025.10.23-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ec13647907bb9d15fd192bbfe89ff06612e098a5709e7d6ecabbdd8f7908fc45", size = 288797, upload-time = "2025-10-21T15:55:21.932Z" }, + { url = "https://files.pythonhosted.org/packages/be/95/888f069c89e7729732a6d7cca37f76b44bfb53a1e35dda8a2c7b65c1b992/regex-2025.10.23-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78d76dd2957d62501084e7012ddafc5fcd406dd982b7a9ca1ea76e8eaaf73e7e", size = 798442, upload-time = "2025-10-21T15:55:23.747Z" }, + { url = "https://files.pythonhosted.org/packages/76/70/4f903c608faf786627a8ee17c06e0067b5acade473678b69c8094b248705/regex-2025.10.23-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8668e5f067e31a47699ebb354f43aeb9c0ef136f915bd864243098524482ac43", size = 864039, upload-time = "2025-10-21T15:55:25.656Z" }, + { url = "https://files.pythonhosted.org/packages/62/19/2df67b526bf25756c7f447dde554fc10a220fd839cc642f50857d01e4a7b/regex-2025.10.23-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a32433fe3deb4b2d8eda88790d2808fed0dc097e84f5e683b4cd4f42edef6cca", size = 912057, upload-time = "2025-10-21T15:55:27.309Z" }, + { url = "https://files.pythonhosted.org/packages/99/14/9a39b7c9e007968411bc3c843cc14cf15437510c0a9991f080cab654fd16/regex-2025.10.23-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d97d73818c642c938db14c0668167f8d39520ca9d983604575ade3fda193afcc", size = 803374, upload-time = "2025-10-21T15:55:28.9Z" }, + { url = "https://files.pythonhosted.org/packages/d4/f7/3495151dd3ca79949599b6d069b72a61a2c5e24fc441dccc79dcaf708fe6/regex-2025.10.23-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bca7feecc72ee33579e9f6ddf8babbe473045717a0e7dbc347099530f96e8b9a", size = 787714, upload-time = "2025-10-21T15:55:30.628Z" }, + { url = "https://files.pythonhosted.org/packages/28/65/ee882455e051131869957ee8597faea45188c9a98c0dad724cfb302d4580/regex-2025.10.23-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7e24af51e907d7457cc4a72691ec458320b9ae67dc492f63209f01eecb09de32", size = 858392, upload-time = "2025-10-21T15:55:32.322Z" }, + { url = "https://files.pythonhosted.org/packages/53/25/9287fef5be97529ebd3ac79d256159cb709a07eb58d4be780d1ca3885da8/regex-2025.10.23-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d10bcde58bbdf18146f3a69ec46dd03233b94a4a5632af97aa5378da3a47d288", size = 850484, upload-time = "2025-10-21T15:55:34.037Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b4/b49b88b4fea2f14dc73e5b5842755e782fc2e52f74423d6f4adc130d5880/regex-2025.10.23-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:44383bc0c933388516c2692c9a7503e1f4a67e982f20b9a29d2fb70c6494f147", size = 789634, upload-time = "2025-10-21T15:55:35.958Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3c/2f8d199d0e84e78bcd6bdc2be9b62410624f6b796e2893d1837ae738b160/regex-2025.10.23-cp312-cp312-win32.whl", hash = "sha256:6040a86f95438a0114bba16e51dfe27f1bc004fd29fe725f54a586f6d522b079", size = 266060, upload-time = "2025-10-21T15:55:37.902Z" }, + { url = "https://files.pythonhosted.org/packages/d7/67/c35e80969f6ded306ad70b0698863310bdf36aca57ad792f45ddc0e2271f/regex-2025.10.23-cp312-cp312-win_amd64.whl", hash = "sha256:436b4c4352fe0762e3bfa34a5567079baa2ef22aa9c37cf4d128979ccfcad842", size = 276931, upload-time = "2025-10-21T15:55:39.502Z" }, + { url = "https://files.pythonhosted.org/packages/f5/a1/4ed147de7d2b60174f758412c87fa51ada15cd3296a0ff047f4280aaa7ca/regex-2025.10.23-cp312-cp312-win_arm64.whl", hash = "sha256:f4b1b1991617055b46aff6f6db24888c1f05f4db9801349d23f09ed0714a9335", size = 270103, upload-time = "2025-10-21T15:55:41.24Z" }, + { url = "https://files.pythonhosted.org/packages/28/c6/195a6217a43719d5a6a12cc192a22d12c40290cecfa577f00f4fb822f07d/regex-2025.10.23-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:b7690f95404a1293923a296981fd943cca12c31a41af9c21ba3edd06398fc193", size = 488956, upload-time = "2025-10-21T15:55:42.887Z" }, + { url = "https://files.pythonhosted.org/packages/4c/93/181070cd1aa2fa541ff2d3afcf763ceecd4937b34c615fa92765020a6c90/regex-2025.10.23-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1a32d77aeaea58a13230100dd8797ac1a84c457f3af2fdf0d81ea689d5a9105b", size = 290997, upload-time = "2025-10-21T15:55:44.53Z" }, + { url = "https://files.pythonhosted.org/packages/b6/c5/9d37fbe3a40ed8dda78c23e1263002497540c0d1522ed75482ef6c2000f0/regex-2025.10.23-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b24b29402f264f70a3c81f45974323b41764ff7159655360543b7cabb73e7d2f", size = 288686, upload-time = "2025-10-21T15:55:46.186Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e7/db610ff9f10c2921f9b6ac0c8d8be4681b28ddd40fc0549429366967e61f/regex-2025.10.23-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:563824a08c7c03d96856d84b46fdb3bbb7cfbdf79da7ef68725cda2ce169c72a", size = 798466, upload-time = "2025-10-21T15:55:48.24Z" }, + { url = "https://files.pythonhosted.org/packages/90/10/aab883e1fa7fe2feb15ac663026e70ca0ae1411efa0c7a4a0342d9545015/regex-2025.10.23-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0ec8bdd88d2e2659c3518087ee34b37e20bd169419ffead4240a7004e8ed03b", size = 863996, upload-time = "2025-10-21T15:55:50.478Z" }, + { url = "https://files.pythonhosted.org/packages/a2/b0/8f686dd97a51f3b37d0238cd00a6d0f9ccabe701f05b56de1918571d0d61/regex-2025.10.23-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b577601bfe1d33913fcd9276d7607bbac827c4798d9e14d04bf37d417a6c41cb", size = 912145, upload-time = "2025-10-21T15:55:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ca/639f8cd5b08797bca38fc5e7e07f76641a428cf8c7fca05894caf045aa32/regex-2025.10.23-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c9f2c68ac6cb3de94eea08a437a75eaa2bd33f9e97c84836ca0b610a5804368", size = 803370, upload-time = "2025-10-21T15:55:53.944Z" }, + { url = "https://files.pythonhosted.org/packages/0d/1e/a40725bb76959eddf8abc42a967bed6f4851b39f5ac4f20e9794d7832aa5/regex-2025.10.23-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:89f8b9ea3830c79468e26b0e21c3585f69f105157c2154a36f6b7839f8afb351", size = 787767, upload-time = "2025-10-21T15:55:56.004Z" }, + { url = "https://files.pythonhosted.org/packages/3d/d8/8ee9858062936b0f99656dce390aa667c6e7fb0c357b1b9bf76fb5e2e708/regex-2025.10.23-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:98fd84c4e4ea185b3bb5bf065261ab45867d8875032f358a435647285c722673", size = 858335, upload-time = "2025-10-21T15:55:58.185Z" }, + { url = "https://files.pythonhosted.org/packages/d8/0a/ed5faaa63fa8e3064ab670e08061fbf09e3a10235b19630cf0cbb9e48c0a/regex-2025.10.23-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1e11d3e5887b8b096f96b4154dfb902f29c723a9556639586cd140e77e28b313", size = 850402, upload-time = "2025-10-21T15:56:00.023Z" }, + { url = "https://files.pythonhosted.org/packages/79/14/d05f617342f4b2b4a23561da500ca2beab062bfcc408d60680e77ecaf04d/regex-2025.10.23-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f13450328a6634348d47a88367e06b64c9d84980ef6a748f717b13f8ce64e87", size = 789739, upload-time = "2025-10-21T15:56:01.967Z" }, + { url = "https://files.pythonhosted.org/packages/f9/7b/e8ce8eef42a15f2c3461f8b3e6e924bbc86e9605cb534a393aadc8d3aff8/regex-2025.10.23-cp313-cp313-win32.whl", hash = "sha256:37be9296598a30c6a20236248cb8b2c07ffd54d095b75d3a2a2ee5babdc51df1", size = 266054, upload-time = "2025-10-21T15:56:05.291Z" }, + { url = "https://files.pythonhosted.org/packages/71/2d/55184ed6be6473187868d2f2e6a0708195fc58270e62a22cbf26028f2570/regex-2025.10.23-cp313-cp313-win_amd64.whl", hash = "sha256:ea7a3c283ce0f06fe789365841e9174ba05f8db16e2fd6ae00a02df9572c04c0", size = 276917, upload-time = "2025-10-21T15:56:07.303Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d4/927eced0e2bd45c45839e556f987f8c8f8683268dd3c00ad327deb3b0172/regex-2025.10.23-cp313-cp313-win_arm64.whl", hash = "sha256:d9a4953575f300a7bab71afa4cd4ac061c7697c89590a2902b536783eeb49a4f", size = 270105, upload-time = "2025-10-21T15:56:09.857Z" }, + { url = "https://files.pythonhosted.org/packages/3e/b3/95b310605285573341fc062d1d30b19a54f857530e86c805f942c4ff7941/regex-2025.10.23-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:7d6606524fa77b3912c9ef52a42ef63c6cfbfc1077e9dc6296cd5da0da286044", size = 491850, upload-time = "2025-10-21T15:56:11.685Z" }, + { url = "https://files.pythonhosted.org/packages/a4/8f/207c2cec01e34e56db1eff606eef46644a60cf1739ecd474627db90ad90b/regex-2025.10.23-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c037aadf4d64bdc38af7db3dbd34877a057ce6524eefcb2914d6d41c56f968cc", size = 292537, upload-time = "2025-10-21T15:56:13.963Z" }, + { url = "https://files.pythonhosted.org/packages/98/3b/025240af4ada1dc0b5f10d73f3e5122d04ce7f8908ab8881e5d82b9d61b6/regex-2025.10.23-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:99018c331fb2529084a0c9b4c713dfa49fafb47c7712422e49467c13a636c656", size = 290904, upload-time = "2025-10-21T15:56:16.016Z" }, + { url = "https://files.pythonhosted.org/packages/81/8e/104ac14e2d3450c43db18ec03e1b96b445a94ae510b60138f00ce2cb7ca1/regex-2025.10.23-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd8aba965604d70306eb90a35528f776e59112a7114a5162824d43b76fa27f58", size = 807311, upload-time = "2025-10-21T15:56:17.818Z" }, + { url = "https://files.pythonhosted.org/packages/19/63/78aef90141b7ce0be8a18e1782f764f6997ad09de0e05251f0d2503a914a/regex-2025.10.23-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:238e67264b4013e74136c49f883734f68656adf8257bfa13b515626b31b20f8e", size = 873241, upload-time = "2025-10-21T15:56:19.941Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a8/80eb1201bb49ae4dba68a1b284b4211ed9daa8e74dc600018a10a90399fb/regex-2025.10.23-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b2eb48bd9848d66fd04826382f5e8491ae633de3233a3d64d58ceb4ecfa2113a", size = 914794, upload-time = "2025-10-21T15:56:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d5/1984b6ee93281f360a119a5ca1af6a8ca7d8417861671388bf750becc29b/regex-2025.10.23-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d36591ce06d047d0c0fe2fc5f14bfbd5b4525d08a7b6a279379085e13f0e3d0e", size = 812581, upload-time = "2025-10-21T15:56:24.319Z" }, + { url = "https://files.pythonhosted.org/packages/c4/39/11ebdc6d9927172a64ae237d16763145db6bd45ebb4055c17b88edab72a7/regex-2025.10.23-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b5d4ece8628d6e364302006366cea3ee887db397faebacc5dacf8ef19e064cf8", size = 795346, upload-time = "2025-10-21T15:56:26.232Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b4/89a591bcc08b5e436af43315284bd233ba77daf0cf20e098d7af12f006c1/regex-2025.10.23-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:39a7e8083959cb1c4ff74e483eecb5a65d3b3e1d821b256e54baf61782c906c6", size = 868214, upload-time = "2025-10-21T15:56:28.597Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ff/58ba98409c1dbc8316cdb20dafbc63ed267380a07780cafecaf5012dabc9/regex-2025.10.23-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:842d449a8fefe546f311656cf8c0d6729b08c09a185f1cad94c756210286d6a8", size = 854540, upload-time = "2025-10-21T15:56:30.875Z" }, + { url = "https://files.pythonhosted.org/packages/9a/f2/4a9e9338d67626e2071b643f828a482712ad15889d7268e11e9a63d6f7e9/regex-2025.10.23-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d614986dc68506be8f00474f4f6960e03e4ca9883f7df47744800e7d7c08a494", size = 799346, upload-time = "2025-10-21T15:56:32.725Z" }, + { url = "https://files.pythonhosted.org/packages/63/be/543d35c46bebf6f7bf2be538cca74d6585f25714700c36f37f01b92df551/regex-2025.10.23-cp313-cp313t-win32.whl", hash = "sha256:a5b7a26b51a9df473ec16a1934d117443a775ceb7b39b78670b2e21893c330c9", size = 268657, upload-time = "2025-10-21T15:56:34.577Z" }, + { url = "https://files.pythonhosted.org/packages/14/9f/4dd6b7b612037158bb2c9bcaa710e6fb3c40ad54af441b9c53b3a137a9f1/regex-2025.10.23-cp313-cp313t-win_amd64.whl", hash = "sha256:ce81c5544a5453f61cb6f548ed358cfb111e3b23f3cd42d250a4077a6be2a7b6", size = 280075, upload-time = "2025-10-21T15:56:36.767Z" }, + { url = "https://files.pythonhosted.org/packages/81/7a/5bd0672aa65d38c8da6747c17c8b441bdb53d816c569e3261013af8e83cf/regex-2025.10.23-cp313-cp313t-win_arm64.whl", hash = "sha256:e9bf7f6699f490e4e43c44757aa179dab24d1960999c84ab5c3d5377714ed473", size = 271219, upload-time = "2025-10-21T15:56:39.033Z" }, + { url = "https://files.pythonhosted.org/packages/73/f6/0caf29fec943f201fbc8822879c99d31e59c1d51a983d9843ee5cf398539/regex-2025.10.23-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:5b5cb5b6344c4c4c24b2dc87b0bfee78202b07ef7633385df70da7fcf6f7cec6", size = 488960, upload-time = "2025-10-21T15:56:40.849Z" }, + { url = "https://files.pythonhosted.org/packages/8e/7d/ebb7085b8fa31c24ce0355107cea2b92229d9050552a01c5d291c42aecea/regex-2025.10.23-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a6ce7973384c37bdf0f371a843f95a6e6f4e1489e10e0cf57330198df72959c5", size = 290932, upload-time = "2025-10-21T15:56:42.875Z" }, + { url = "https://files.pythonhosted.org/packages/27/41/43906867287cbb5ca4cee671c3cc8081e15deef86a8189c3aad9ac9f6b4d/regex-2025.10.23-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2ee3663f2c334959016b56e3bd0dd187cbc73f948e3a3af14c3caaa0c3035d10", size = 288766, upload-time = "2025-10-21T15:56:44.894Z" }, + { url = "https://files.pythonhosted.org/packages/ab/9e/ea66132776700fc77a39b1056e7a5f1308032fead94507e208dc6716b7cd/regex-2025.10.23-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2003cc82a579107e70d013482acce8ba773293f2db534fb532738395c557ff34", size = 798884, upload-time = "2025-10-21T15:56:47.178Z" }, + { url = "https://files.pythonhosted.org/packages/d5/99/aed1453687ab63819a443930770db972c5c8064421f0d9f5da9ad029f26b/regex-2025.10.23-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:182c452279365a93a9f45874f7f191ec1c51e1f1eb41bf2b16563f1a40c1da3a", size = 864768, upload-time = "2025-10-21T15:56:49.793Z" }, + { url = "https://files.pythonhosted.org/packages/99/5d/732fe747a1304805eb3853ce6337eea16b169f7105a0d0dd9c6a5ffa9948/regex-2025.10.23-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b1249e9ff581c5b658c8f0437f883b01f1edcf424a16388591e7c05e5e9e8b0c", size = 911394, upload-time = "2025-10-21T15:56:52.186Z" }, + { url = "https://files.pythonhosted.org/packages/5e/48/58a1f6623466522352a6efa153b9a3714fc559d9f930e9bc947b4a88a2c3/regex-2025.10.23-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b841698f93db3ccc36caa1900d2a3be281d9539b822dc012f08fc80b46a3224", size = 803145, upload-time = "2025-10-21T15:56:55.142Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f6/7dea79be2681a5574ab3fc237aa53b2c1dfd6bd2b44d4640b6c76f33f4c1/regex-2025.10.23-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:956d89e0c92d471e8f7eee73f73fdff5ed345886378c45a43175a77538a1ffe4", size = 787831, upload-time = "2025-10-21T15:56:57.203Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ad/07b76950fbbe65f88120ca2d8d845047c401450f607c99ed38862904671d/regex-2025.10.23-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5c259cb363299a0d90d63b5c0d7568ee98419861618a95ee9d91a41cb9954462", size = 859162, upload-time = "2025-10-21T15:56:59.195Z" }, + { url = "https://files.pythonhosted.org/packages/41/87/374f3b2021b22aa6a4fc0b750d63f9721e53d1631a238f7a1c343c1cd288/regex-2025.10.23-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:185d2b18c062820b3a40d8fefa223a83f10b20a674bf6e8c4a432e8dfd844627", size = 849899, upload-time = "2025-10-21T15:57:01.747Z" }, + { url = "https://files.pythonhosted.org/packages/12/4a/7f7bb17c5a5a9747249807210e348450dab9212a46ae6d23ebce86ba6a2b/regex-2025.10.23-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:281d87fa790049c2b7c1b4253121edd80b392b19b5a3d28dc2a77579cb2a58ec", size = 789372, upload-time = "2025-10-21T15:57:04.018Z" }, + { url = "https://files.pythonhosted.org/packages/c9/dd/9c7728ff544fea09bbc8635e4c9e7c423b11c24f1a7a14e6ac4831466709/regex-2025.10.23-cp314-cp314-win32.whl", hash = "sha256:63b81eef3656072e4ca87c58084c7a9c2b81d41a300b157be635a8a675aacfb8", size = 271451, upload-time = "2025-10-21T15:57:06.266Z" }, + { url = "https://files.pythonhosted.org/packages/48/f8/ef7837ff858eb74079c4804c10b0403c0b740762e6eedba41062225f7117/regex-2025.10.23-cp314-cp314-win_amd64.whl", hash = "sha256:0967c5b86f274800a34a4ed862dfab56928144d03cb18821c5153f8777947796", size = 280173, upload-time = "2025-10-21T15:57:08.206Z" }, + { url = "https://files.pythonhosted.org/packages/8e/d0/d576e1dbd9885bfcd83d0e90762beea48d9373a6f7ed39170f44ed22e336/regex-2025.10.23-cp314-cp314-win_arm64.whl", hash = "sha256:c70dfe58b0a00b36aa04cdb0f798bf3e0adc31747641f69e191109fd8572c9a9", size = 273206, upload-time = "2025-10-21T15:57:10.367Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d0/2025268315e8b2b7b660039824cb7765a41623e97d4cd421510925400487/regex-2025.10.23-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1f5799ea1787aa6de6c150377d11afad39a38afd033f0c5247aecb997978c422", size = 491854, upload-time = "2025-10-21T15:57:12.526Z" }, + { url = "https://files.pythonhosted.org/packages/44/35/5681c2fec5e8b33454390af209c4353dfc44606bf06d714b0b8bd0454ffe/regex-2025.10.23-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a9639ab7540cfea45ef57d16dcbea2e22de351998d614c3ad2f9778fa3bdd788", size = 292542, upload-time = "2025-10-21T15:57:15.158Z" }, + { url = "https://files.pythonhosted.org/packages/5d/17/184eed05543b724132e4a18149e900f5189001fcfe2d64edaae4fbaf36b4/regex-2025.10.23-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:08f52122c352eb44c3421dab78b9b73a8a77a282cc8314ae576fcaa92b780d10", size = 290903, upload-time = "2025-10-21T15:57:17.108Z" }, + { url = "https://files.pythonhosted.org/packages/25/d0/5e3347aa0db0de382dddfa133a7b0ae72f24b4344f3989398980b44a3924/regex-2025.10.23-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ebf1baebef1c4088ad5a5623decec6b52950f0e4d7a0ae4d48f0a99f8c9cb7d7", size = 807546, upload-time = "2025-10-21T15:57:19.179Z" }, + { url = "https://files.pythonhosted.org/packages/d2/bb/40c589bbdce1be0c55e9f8159789d58d47a22014f2f820cf2b517a5cd193/regex-2025.10.23-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:16b0f1c2e2d566c562d5c384c2b492646be0a19798532fdc1fdedacc66e3223f", size = 873322, upload-time = "2025-10-21T15:57:21.36Z" }, + { url = "https://files.pythonhosted.org/packages/fe/56/a7e40c01575ac93360e606278d359f91829781a9f7fb6e5aa435039edbda/regex-2025.10.23-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7ada5d9dceafaab92646aa00c10a9efd9b09942dd9b0d7c5a4b73db92cc7e61", size = 914855, upload-time = "2025-10-21T15:57:24.044Z" }, + { url = "https://files.pythonhosted.org/packages/5c/4b/d55587b192763db3163c3f508b3b67b31bb6f5e7a0e08b83013d0a59500a/regex-2025.10.23-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a36b4005770044bf08edecc798f0e41a75795b9e7c9c12fe29da8d792ef870c", size = 812724, upload-time = "2025-10-21T15:57:26.123Z" }, + { url = "https://files.pythonhosted.org/packages/33/20/18bac334955fbe99d17229f4f8e98d05e4a501ac03a442be8facbb37c304/regex-2025.10.23-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:af7b2661dcc032da1fae82069b5ebf2ac1dfcd5359ef8b35e1367bfc92181432", size = 795439, upload-time = "2025-10-21T15:57:28.497Z" }, + { url = "https://files.pythonhosted.org/packages/67/46/c57266be9df8549c7d85deb4cb82280cb0019e46fff677534c5fa1badfa4/regex-2025.10.23-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:1cb976810ac1416a67562c2e5ba0accf6f928932320fef302e08100ed681b38e", size = 868336, upload-time = "2025-10-21T15:57:30.867Z" }, + { url = "https://files.pythonhosted.org/packages/b8/f3/bd5879e41ef8187fec5e678e94b526a93f99e7bbe0437b0f2b47f9101694/regex-2025.10.23-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:1a56a54be3897d62f54290190fbcd754bff6932934529fbf5b29933da28fcd43", size = 854567, upload-time = "2025-10-21T15:57:33.062Z" }, + { url = "https://files.pythonhosted.org/packages/e6/57/2b6bbdbd2f24dfed5b028033aa17ad8f7d86bb28f1a892cac8b3bc89d059/regex-2025.10.23-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8f3e6d202fb52c2153f532043bbcf618fd177df47b0b306741eb9b60ba96edc3", size = 799565, upload-time = "2025-10-21T15:57:35.153Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ba/a6168f542ba73b151ed81237adf6b869c7b2f7f8d51618111296674e20ee/regex-2025.10.23-cp314-cp314t-win32.whl", hash = "sha256:1fa1186966b2621b1769fd467c7b22e317e6ba2d2cdcecc42ea3089ef04a8521", size = 274428, upload-time = "2025-10-21T15:57:37.996Z" }, + { url = "https://files.pythonhosted.org/packages/ef/a0/c84475e14a2829e9b0864ebf77c3f7da909df9d8acfe2bb540ff0072047c/regex-2025.10.23-cp314-cp314t-win_amd64.whl", hash = "sha256:08a15d40ce28362eac3e78e83d75475147869c1ff86bc93285f43b4f4431a741", size = 284140, upload-time = "2025-10-21T15:57:40.027Z" }, + { url = "https://files.pythonhosted.org/packages/51/33/6a08ade0eee5b8ba79386869fa6f77afeb835b60510f3525db987e2fffc4/regex-2025.10.23-cp314-cp314t-win_arm64.whl", hash = "sha256:a93e97338e1c8ea2649e130dcfbe8cd69bba5e1e163834752ab64dcb4de6d5ed", size = 274497, upload-time = "2025-10-21T15:57:42.389Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "rich" +version = "14.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, +] + +[[package]] +name = "safetensors" +version = "0.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/cc/738f3011628920e027a11754d9cae9abec1aed00f7ae860abbf843755233/safetensors-0.6.2.tar.gz", hash = "sha256:43ff2aa0e6fa2dc3ea5524ac7ad93a9839256b8703761e76e2d0b2a3fa4f15d9", size = 197968, upload-time = "2025-08-08T13:13:58.654Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/b1/3f5fd73c039fc87dba3ff8b5d528bfc5a32b597fea8e7a6a4800343a17c7/safetensors-0.6.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:9c85ede8ec58f120bad982ec47746981e210492a6db876882aa021446af8ffba", size = 454797, upload-time = "2025-08-08T13:13:52.066Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c9/bb114c158540ee17907ec470d01980957fdaf87b4aa07914c24eba87b9c6/safetensors-0.6.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d6675cf4b39c98dbd7d940598028f3742e0375a6b4d4277e76beb0c35f4b843b", size = 432206, upload-time = "2025-08-08T13:13:50.931Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8e/f70c34e47df3110e8e0bb268d90db8d4be8958a54ab0336c9be4fe86dac8/safetensors-0.6.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d2d2b3ce1e2509c68932ca03ab8f20570920cd9754b05063d4368ee52833ecd", size = 473261, upload-time = "2025-08-08T13:13:41.259Z" }, + { url = "https://files.pythonhosted.org/packages/2a/f5/be9c6a7c7ef773e1996dc214e73485286df1836dbd063e8085ee1976f9cb/safetensors-0.6.2-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:93de35a18f46b0f5a6a1f9e26d91b442094f2df02e9fd7acf224cfec4238821a", size = 485117, upload-time = "2025-08-08T13:13:43.506Z" }, + { url = "https://files.pythonhosted.org/packages/c9/55/23f2d0a2c96ed8665bf17a30ab4ce5270413f4d74b6d87dd663258b9af31/safetensors-0.6.2-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89a89b505f335640f9120fac65ddeb83e40f1fd081cb8ed88b505bdccec8d0a1", size = 616154, upload-time = "2025-08-08T13:13:45.096Z" }, + { url = "https://files.pythonhosted.org/packages/98/c6/affb0bd9ce02aa46e7acddbe087912a04d953d7a4d74b708c91b5806ef3f/safetensors-0.6.2-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc4d0d0b937e04bdf2ae6f70cd3ad51328635fe0e6214aa1fc811f3b576b3bda", size = 520713, upload-time = "2025-08-08T13:13:46.25Z" }, + { url = "https://files.pythonhosted.org/packages/fe/5d/5a514d7b88e310c8b146e2404e0dc161282e78634d9358975fd56dfd14be/safetensors-0.6.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8045db2c872db8f4cbe3faa0495932d89c38c899c603f21e9b6486951a5ecb8f", size = 485835, upload-time = "2025-08-08T13:13:49.373Z" }, + { url = "https://files.pythonhosted.org/packages/7a/7b/4fc3b2ba62c352b2071bea9cfbad330fadda70579f617506ae1a2f129cab/safetensors-0.6.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:81e67e8bab9878bb568cffbc5f5e655adb38d2418351dc0859ccac158f753e19", size = 521503, upload-time = "2025-08-08T13:13:47.651Z" }, + { url = "https://files.pythonhosted.org/packages/5a/50/0057e11fe1f3cead9254315a6c106a16dd4b1a19cd247f7cc6414f6b7866/safetensors-0.6.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b0e4d029ab0a0e0e4fdf142b194514695b1d7d3735503ba700cf36d0fc7136ce", size = 652256, upload-time = "2025-08-08T13:13:53.167Z" }, + { url = "https://files.pythonhosted.org/packages/e9/29/473f789e4ac242593ac1656fbece6e1ecd860bb289e635e963667807afe3/safetensors-0.6.2-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:fa48268185c52bfe8771e46325a1e21d317207bcabcb72e65c6e28e9ffeb29c7", size = 747281, upload-time = "2025-08-08T13:13:54.656Z" }, + { url = "https://files.pythonhosted.org/packages/68/52/f7324aad7f2df99e05525c84d352dc217e0fa637a4f603e9f2eedfbe2c67/safetensors-0.6.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:d83c20c12c2d2f465997c51b7ecb00e407e5f94d7dec3ea0cc11d86f60d3fde5", size = 692286, upload-time = "2025-08-08T13:13:55.884Z" }, + { url = "https://files.pythonhosted.org/packages/ad/fe/cad1d9762868c7c5dc70c8620074df28ebb1a8e4c17d4c0cb031889c457e/safetensors-0.6.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d944cea65fad0ead848b6ec2c37cc0b197194bec228f8020054742190e9312ac", size = 655957, upload-time = "2025-08-08T13:13:57.029Z" }, + { url = "https://files.pythonhosted.org/packages/59/a7/e2158e17bbe57d104f0abbd95dff60dda916cf277c9f9663b4bf9bad8b6e/safetensors-0.6.2-cp38-abi3-win32.whl", hash = "sha256:cab75ca7c064d3911411461151cb69380c9225798a20e712b102edda2542ddb1", size = 308926, upload-time = "2025-08-08T13:14:01.095Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c3/c0be1135726618dc1e28d181b8c442403d8dbb9e273fd791de2d4384bcdd/safetensors-0.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:c7b214870df923cbc1593c3faee16bec59ea462758699bd3fee399d00aac072c", size = 320192, upload-time = "2025-08-08T13:13:59.467Z" }, +] + +[[package]] +name = "scikit-learn" +version = "1.7.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "scipy", version = "1.16.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "threadpoolctl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/c2/a7855e41c9d285dfe86dc50b250978105dce513d6e459ea66a6aeb0e1e0c/scikit_learn-1.7.2.tar.gz", hash = "sha256:20e9e49ecd130598f1ca38a1d85090e1a600147b9c02fa6f15d69cb53d968fda", size = 7193136, upload-time = "2025-09-09T08:21:29.075Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/3e/daed796fd69cce768b8788401cc464ea90b306fb196ae1ffed0b98182859/scikit_learn-1.7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b33579c10a3081d076ab403df4a4190da4f4432d443521674637677dc91e61f", size = 9336221, upload-time = "2025-09-09T08:20:19.328Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ce/af9d99533b24c55ff4e18d9b7b4d9919bbc6cd8f22fe7a7be01519a347d5/scikit_learn-1.7.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:36749fb62b3d961b1ce4fedf08fa57a1986cd409eff2d783bca5d4b9b5fce51c", size = 8653834, upload-time = "2025-09-09T08:20:22.073Z" }, + { url = "https://files.pythonhosted.org/packages/58/0e/8c2a03d518fb6bd0b6b0d4b114c63d5f1db01ff0f9925d8eb10960d01c01/scikit_learn-1.7.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7a58814265dfc52b3295b1900cfb5701589d30a8bb026c7540f1e9d3499d5ec8", size = 9660938, upload-time = "2025-09-09T08:20:24.327Z" }, + { url = "https://files.pythonhosted.org/packages/2b/75/4311605069b5d220e7cf5adabb38535bd96f0079313cdbb04b291479b22a/scikit_learn-1.7.2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a847fea807e278f821a0406ca01e387f97653e284ecbd9750e3ee7c90347f18", size = 9477818, upload-time = "2025-09-09T08:20:26.845Z" }, + { url = "https://files.pythonhosted.org/packages/7f/9b/87961813c34adbca21a6b3f6b2bea344c43b30217a6d24cc437c6147f3e8/scikit_learn-1.7.2-cp310-cp310-win_amd64.whl", hash = "sha256:ca250e6836d10e6f402436d6463d6c0e4d8e0234cfb6a9a47835bd392b852ce5", size = 8886969, upload-time = "2025-09-09T08:20:29.329Z" }, + { url = "https://files.pythonhosted.org/packages/43/83/564e141eef908a5863a54da8ca342a137f45a0bfb71d1d79704c9894c9d1/scikit_learn-1.7.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7509693451651cd7361d30ce4e86a1347493554f172b1c72a39300fa2aea79e", size = 9331967, upload-time = "2025-09-09T08:20:32.421Z" }, + { url = "https://files.pythonhosted.org/packages/18/d6/ba863a4171ac9d7314c4d3fc251f015704a2caeee41ced89f321c049ed83/scikit_learn-1.7.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:0486c8f827c2e7b64837c731c8feff72c0bd2b998067a8a9cbc10643c31f0fe1", size = 8648645, upload-time = "2025-09-09T08:20:34.436Z" }, + { url = "https://files.pythonhosted.org/packages/ef/0e/97dbca66347b8cf0ea8b529e6bb9367e337ba2e8be0ef5c1a545232abfde/scikit_learn-1.7.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:89877e19a80c7b11a2891a27c21c4894fb18e2c2e077815bcade10d34287b20d", size = 9715424, upload-time = "2025-09-09T08:20:36.776Z" }, + { url = "https://files.pythonhosted.org/packages/f7/32/1f3b22e3207e1d2c883a7e09abb956362e7d1bd2f14458c7de258a26ac15/scikit_learn-1.7.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8da8bf89d4d79aaec192d2bda62f9b56ae4e5b4ef93b6a56b5de4977e375c1f1", size = 9509234, upload-time = "2025-09-09T08:20:38.957Z" }, + { url = "https://files.pythonhosted.org/packages/9f/71/34ddbd21f1da67c7a768146968b4d0220ee6831e4bcbad3e03dd3eae88b6/scikit_learn-1.7.2-cp311-cp311-win_amd64.whl", hash = "sha256:9b7ed8d58725030568523e937c43e56bc01cadb478fc43c042a9aca1dacb3ba1", size = 8894244, upload-time = "2025-09-09T08:20:41.166Z" }, + { url = "https://files.pythonhosted.org/packages/a7/aa/3996e2196075689afb9fce0410ebdb4a09099d7964d061d7213700204409/scikit_learn-1.7.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8d91a97fa2b706943822398ab943cde71858a50245e31bc71dba62aab1d60a96", size = 9259818, upload-time = "2025-09-09T08:20:43.19Z" }, + { url = "https://files.pythonhosted.org/packages/43/5d/779320063e88af9c4a7c2cf463ff11c21ac9c8bd730c4a294b0000b666c9/scikit_learn-1.7.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:acbc0f5fd2edd3432a22c69bed78e837c70cf896cd7993d71d51ba6708507476", size = 8636997, upload-time = "2025-09-09T08:20:45.468Z" }, + { url = "https://files.pythonhosted.org/packages/5c/d0/0c577d9325b05594fdd33aa970bf53fb673f051a45496842caee13cfd7fe/scikit_learn-1.7.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e5bf3d930aee75a65478df91ac1225ff89cd28e9ac7bd1196853a9229b6adb0b", size = 9478381, upload-time = "2025-09-09T08:20:47.982Z" }, + { url = "https://files.pythonhosted.org/packages/82/70/8bf44b933837ba8494ca0fc9a9ab60f1c13b062ad0197f60a56e2fc4c43e/scikit_learn-1.7.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4d6e9deed1a47aca9fe2f267ab8e8fe82ee20b4526b2c0cd9e135cea10feb44", size = 9300296, upload-time = "2025-09-09T08:20:50.366Z" }, + { url = "https://files.pythonhosted.org/packages/c6/99/ed35197a158f1fdc2fe7c3680e9c70d0128f662e1fee4ed495f4b5e13db0/scikit_learn-1.7.2-cp312-cp312-win_amd64.whl", hash = "sha256:6088aa475f0785e01bcf8529f55280a3d7d298679f50c0bb70a2364a82d0b290", size = 8731256, upload-time = "2025-09-09T08:20:52.627Z" }, + { url = "https://files.pythonhosted.org/packages/ae/93/a3038cb0293037fd335f77f31fe053b89c72f17b1c8908c576c29d953e84/scikit_learn-1.7.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0b7dacaa05e5d76759fb071558a8b5130f4845166d88654a0f9bdf3eb57851b7", size = 9212382, upload-time = "2025-09-09T08:20:54.731Z" }, + { url = "https://files.pythonhosted.org/packages/40/dd/9a88879b0c1104259136146e4742026b52df8540c39fec21a6383f8292c7/scikit_learn-1.7.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:abebbd61ad9e1deed54cca45caea8ad5f79e1b93173dece40bb8e0c658dbe6fe", size = 8592042, upload-time = "2025-09-09T08:20:57.313Z" }, + { url = "https://files.pythonhosted.org/packages/46/af/c5e286471b7d10871b811b72ae794ac5fe2989c0a2df07f0ec723030f5f5/scikit_learn-1.7.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:502c18e39849c0ea1a5d681af1dbcf15f6cce601aebb657aabbfe84133c1907f", size = 9434180, upload-time = "2025-09-09T08:20:59.671Z" }, + { url = "https://files.pythonhosted.org/packages/f1/fd/df59faa53312d585023b2da27e866524ffb8faf87a68516c23896c718320/scikit_learn-1.7.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a4c328a71785382fe3fe676a9ecf2c86189249beff90bf85e22bdb7efaf9ae0", size = 9283660, upload-time = "2025-09-09T08:21:01.71Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c7/03000262759d7b6f38c836ff9d512f438a70d8a8ddae68ee80de72dcfb63/scikit_learn-1.7.2-cp313-cp313-win_amd64.whl", hash = "sha256:63a9afd6f7b229aad94618c01c252ce9e6fa97918c5ca19c9a17a087d819440c", size = 8702057, upload-time = "2025-09-09T08:21:04.234Z" }, + { url = "https://files.pythonhosted.org/packages/55/87/ef5eb1f267084532c8e4aef98a28b6ffe7425acbfd64b5e2f2e066bc29b3/scikit_learn-1.7.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9acb6c5e867447b4e1390930e3944a005e2cb115922e693c08a323421a6966e8", size = 9558731, upload-time = "2025-09-09T08:21:06.381Z" }, + { url = "https://files.pythonhosted.org/packages/93/f8/6c1e3fc14b10118068d7938878a9f3f4e6d7b74a8ddb1e5bed65159ccda8/scikit_learn-1.7.2-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:2a41e2a0ef45063e654152ec9d8bcfc39f7afce35b08902bfe290c2498a67a6a", size = 9038852, upload-time = "2025-09-09T08:21:08.628Z" }, + { url = "https://files.pythonhosted.org/packages/83/87/066cafc896ee540c34becf95d30375fe5cbe93c3b75a0ee9aa852cd60021/scikit_learn-1.7.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:98335fb98509b73385b3ab2bd0639b1f610541d3988ee675c670371d6a87aa7c", size = 9527094, upload-time = "2025-09-09T08:21:11.486Z" }, + { url = "https://files.pythonhosted.org/packages/9c/2b/4903e1ccafa1f6453b1ab78413938c8800633988c838aa0be386cbb33072/scikit_learn-1.7.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:191e5550980d45449126e23ed1d5e9e24b2c68329ee1f691a3987476e115e09c", size = 9367436, upload-time = "2025-09-09T08:21:13.602Z" }, + { url = "https://files.pythonhosted.org/packages/b5/aa/8444be3cfb10451617ff9d177b3c190288f4563e6c50ff02728be67ad094/scikit_learn-1.7.2-cp313-cp313t-win_amd64.whl", hash = "sha256:57dc4deb1d3762c75d685507fbd0bc17160144b2f2ba4ccea5dc285ab0d0e973", size = 9275749, upload-time = "2025-09-09T08:21:15.96Z" }, + { url = "https://files.pythonhosted.org/packages/d9/82/dee5acf66837852e8e68df6d8d3a6cb22d3df997b733b032f513d95205b7/scikit_learn-1.7.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fa8f63940e29c82d1e67a45d5297bdebbcb585f5a5a50c4914cc2e852ab77f33", size = 9208906, upload-time = "2025-09-09T08:21:18.557Z" }, + { url = "https://files.pythonhosted.org/packages/3c/30/9029e54e17b87cb7d50d51a5926429c683d5b4c1732f0507a6c3bed9bf65/scikit_learn-1.7.2-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:f95dc55b7902b91331fa4e5845dd5bde0580c9cd9612b1b2791b7e80c3d32615", size = 8627836, upload-time = "2025-09-09T08:21:20.695Z" }, + { url = "https://files.pythonhosted.org/packages/60/18/4a52c635c71b536879f4b971c2cedf32c35ee78f48367885ed8025d1f7ee/scikit_learn-1.7.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9656e4a53e54578ad10a434dc1f993330568cfee176dff07112b8785fb413106", size = 9426236, upload-time = "2025-09-09T08:21:22.645Z" }, + { url = "https://files.pythonhosted.org/packages/99/7e/290362f6ab582128c53445458a5befd471ed1ea37953d5bcf80604619250/scikit_learn-1.7.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96dc05a854add0e50d3f47a1ef21a10a595016da5b007c7d9cd9d0bffd1fcc61", size = 9312593, upload-time = "2025-09-09T08:21:24.65Z" }, + { url = "https://files.pythonhosted.org/packages/8e/87/24f541b6d62b1794939ae6422f8023703bbf6900378b2b34e0b4384dfefd/scikit_learn-1.7.2-cp314-cp314-win_amd64.whl", hash = "sha256:bb24510ed3f9f61476181e4db51ce801e2ba37541def12dc9333b946fc7a9cf8", size = 8820007, upload-time = "2025-09-09T08:21:26.713Z" }, +] + +[[package]] +name = "scipy" +version = "1.15.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/2f/4966032c5f8cc7e6a60f1b2e0ad686293b9474b65246b0c642e3ef3badd0/scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c", size = 38702770, upload-time = "2025-05-08T16:04:20.849Z" }, + { url = "https://files.pythonhosted.org/packages/a0/6e/0c3bf90fae0e910c274db43304ebe25a6b391327f3f10b5dcc638c090795/scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253", size = 30094511, upload-time = "2025-05-08T16:04:27.103Z" }, + { url = "https://files.pythonhosted.org/packages/ea/b1/4deb37252311c1acff7f101f6453f0440794f51b6eacb1aad4459a134081/scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f", size = 22368151, upload-time = "2025-05-08T16:04:31.731Z" }, + { url = "https://files.pythonhosted.org/packages/38/7d/f457626e3cd3c29b3a49ca115a304cebb8cc6f31b04678f03b216899d3c6/scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92", size = 25121732, upload-time = "2025-05-08T16:04:36.596Z" }, + { url = "https://files.pythonhosted.org/packages/db/0a/92b1de4a7adc7a15dcf5bddc6e191f6f29ee663b30511ce20467ef9b82e4/scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82", size = 35547617, upload-time = "2025-05-08T16:04:43.546Z" }, + { url = "https://files.pythonhosted.org/packages/8e/6d/41991e503e51fc1134502694c5fa7a1671501a17ffa12716a4a9151af3df/scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40", size = 37662964, upload-time = "2025-05-08T16:04:49.431Z" }, + { url = "https://files.pythonhosted.org/packages/25/e1/3df8f83cb15f3500478c889be8fb18700813b95e9e087328230b98d547ff/scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e", size = 37238749, upload-time = "2025-05-08T16:04:55.215Z" }, + { url = "https://files.pythonhosted.org/packages/93/3e/b3257cf446f2a3533ed7809757039016b74cd6f38271de91682aa844cfc5/scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c", size = 40022383, upload-time = "2025-05-08T16:05:01.914Z" }, + { url = "https://files.pythonhosted.org/packages/d1/84/55bc4881973d3f79b479a5a2e2df61c8c9a04fcb986a213ac9c02cfb659b/scipy-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13", size = 41259201, upload-time = "2025-05-08T16:05:08.166Z" }, + { url = "https://files.pythonhosted.org/packages/96/ab/5cc9f80f28f6a7dff646c5756e559823614a42b1939d86dd0ed550470210/scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b", size = 38714255, upload-time = "2025-05-08T16:05:14.596Z" }, + { url = "https://files.pythonhosted.org/packages/4a/4a/66ba30abe5ad1a3ad15bfb0b59d22174012e8056ff448cb1644deccbfed2/scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba", size = 30111035, upload-time = "2025-05-08T16:05:20.152Z" }, + { url = "https://files.pythonhosted.org/packages/4b/fa/a7e5b95afd80d24313307f03624acc65801846fa75599034f8ceb9e2cbf6/scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65", size = 22384499, upload-time = "2025-05-08T16:05:24.494Z" }, + { url = "https://files.pythonhosted.org/packages/17/99/f3aaddccf3588bb4aea70ba35328c204cadd89517a1612ecfda5b2dd9d7a/scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1", size = 25152602, upload-time = "2025-05-08T16:05:29.313Z" }, + { url = "https://files.pythonhosted.org/packages/56/c5/1032cdb565f146109212153339f9cb8b993701e9fe56b1c97699eee12586/scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889", size = 35503415, upload-time = "2025-05-08T16:05:34.699Z" }, + { url = "https://files.pythonhosted.org/packages/bd/37/89f19c8c05505d0601ed5650156e50eb881ae3918786c8fd7262b4ee66d3/scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982", size = 37652622, upload-time = "2025-05-08T16:05:40.762Z" }, + { url = "https://files.pythonhosted.org/packages/7e/31/be59513aa9695519b18e1851bb9e487de66f2d31f835201f1b42f5d4d475/scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9", size = 37244796, upload-time = "2025-05-08T16:05:48.119Z" }, + { url = "https://files.pythonhosted.org/packages/10/c0/4f5f3eeccc235632aab79b27a74a9130c6c35df358129f7ac8b29f562ac7/scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594", size = 40047684, upload-time = "2025-05-08T16:05:54.22Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a7/0ddaf514ce8a8714f6ed243a2b391b41dbb65251affe21ee3077ec45ea9a/scipy-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb", size = 41246504, upload-time = "2025-05-08T16:06:00.437Z" }, + { url = "https://files.pythonhosted.org/packages/37/4b/683aa044c4162e10ed7a7ea30527f2cbd92e6999c10a8ed8edb253836e9c/scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019", size = 38766735, upload-time = "2025-05-08T16:06:06.471Z" }, + { url = "https://files.pythonhosted.org/packages/7b/7e/f30be3d03de07f25dc0ec926d1681fed5c732d759ac8f51079708c79e680/scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6", size = 30173284, upload-time = "2025-05-08T16:06:11.686Z" }, + { url = "https://files.pythonhosted.org/packages/07/9c/0ddb0d0abdabe0d181c1793db51f02cd59e4901da6f9f7848e1f96759f0d/scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477", size = 22446958, upload-time = "2025-05-08T16:06:15.97Z" }, + { url = "https://files.pythonhosted.org/packages/af/43/0bce905a965f36c58ff80d8bea33f1f9351b05fad4beaad4eae34699b7a1/scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c", size = 25242454, upload-time = "2025-05-08T16:06:20.394Z" }, + { url = "https://files.pythonhosted.org/packages/56/30/a6f08f84ee5b7b28b4c597aca4cbe545535c39fe911845a96414700b64ba/scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45", size = 35210199, upload-time = "2025-05-08T16:06:26.159Z" }, + { url = "https://files.pythonhosted.org/packages/0b/1f/03f52c282437a168ee2c7c14a1a0d0781a9a4a8962d84ac05c06b4c5b555/scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49", size = 37309455, upload-time = "2025-05-08T16:06:32.778Z" }, + { url = "https://files.pythonhosted.org/packages/89/b1/fbb53137f42c4bf630b1ffdfc2151a62d1d1b903b249f030d2b1c0280af8/scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e", size = 36885140, upload-time = "2025-05-08T16:06:39.249Z" }, + { url = "https://files.pythonhosted.org/packages/2e/2e/025e39e339f5090df1ff266d021892694dbb7e63568edcfe43f892fa381d/scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539", size = 39710549, upload-time = "2025-05-08T16:06:45.729Z" }, + { url = "https://files.pythonhosted.org/packages/e6/eb/3bf6ea8ab7f1503dca3a10df2e4b9c3f6b3316df07f6c0ded94b281c7101/scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed", size = 40966184, upload-time = "2025-05-08T16:06:52.623Z" }, + { url = "https://files.pythonhosted.org/packages/73/18/ec27848c9baae6e0d6573eda6e01a602e5649ee72c27c3a8aad673ebecfd/scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759", size = 38728256, upload-time = "2025-05-08T16:06:58.696Z" }, + { url = "https://files.pythonhosted.org/packages/74/cd/1aef2184948728b4b6e21267d53b3339762c285a46a274ebb7863c9e4742/scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62", size = 30109540, upload-time = "2025-05-08T16:07:04.209Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d8/59e452c0a255ec352bd0a833537a3bc1bfb679944c4938ab375b0a6b3a3e/scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb", size = 22383115, upload-time = "2025-05-08T16:07:08.998Z" }, + { url = "https://files.pythonhosted.org/packages/08/f5/456f56bbbfccf696263b47095291040655e3cbaf05d063bdc7c7517f32ac/scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730", size = 25163884, upload-time = "2025-05-08T16:07:14.091Z" }, + { url = "https://files.pythonhosted.org/packages/a2/66/a9618b6a435a0f0c0b8a6d0a2efb32d4ec5a85f023c2b79d39512040355b/scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825", size = 35174018, upload-time = "2025-05-08T16:07:19.427Z" }, + { url = "https://files.pythonhosted.org/packages/b5/09/c5b6734a50ad4882432b6bb7c02baf757f5b2f256041da5df242e2d7e6b6/scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7", size = 37269716, upload-time = "2025-05-08T16:07:25.712Z" }, + { url = "https://files.pythonhosted.org/packages/77/0a/eac00ff741f23bcabd352731ed9b8995a0a60ef57f5fd788d611d43d69a1/scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11", size = 36872342, upload-time = "2025-05-08T16:07:31.468Z" }, + { url = "https://files.pythonhosted.org/packages/fe/54/4379be86dd74b6ad81551689107360d9a3e18f24d20767a2d5b9253a3f0a/scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126", size = 39670869, upload-time = "2025-05-08T16:07:38.002Z" }, + { url = "https://files.pythonhosted.org/packages/87/2e/892ad2862ba54f084ffe8cc4a22667eaf9c2bcec6d2bff1d15713c6c0703/scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163", size = 40988851, upload-time = "2025-05-08T16:08:33.671Z" }, + { url = "https://files.pythonhosted.org/packages/1b/e9/7a879c137f7e55b30d75d90ce3eb468197646bc7b443ac036ae3fe109055/scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8", size = 38863011, upload-time = "2025-05-08T16:07:44.039Z" }, + { url = "https://files.pythonhosted.org/packages/51/d1/226a806bbd69f62ce5ef5f3ffadc35286e9fbc802f606a07eb83bf2359de/scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5", size = 30266407, upload-time = "2025-05-08T16:07:49.891Z" }, + { url = "https://files.pythonhosted.org/packages/e5/9b/f32d1d6093ab9eeabbd839b0f7619c62e46cc4b7b6dbf05b6e615bbd4400/scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e", size = 22540030, upload-time = "2025-05-08T16:07:54.121Z" }, + { url = "https://files.pythonhosted.org/packages/e7/29/c278f699b095c1a884f29fda126340fcc201461ee8bfea5c8bdb1c7c958b/scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb", size = 25218709, upload-time = "2025-05-08T16:07:58.506Z" }, + { url = "https://files.pythonhosted.org/packages/24/18/9e5374b617aba742a990581373cd6b68a2945d65cc588482749ef2e64467/scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723", size = 34809045, upload-time = "2025-05-08T16:08:03.929Z" }, + { url = "https://files.pythonhosted.org/packages/e1/fe/9c4361e7ba2927074360856db6135ef4904d505e9b3afbbcb073c4008328/scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb", size = 36703062, upload-time = "2025-05-08T16:08:09.558Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8e/038ccfe29d272b30086b25a4960f757f97122cb2ec42e62b460d02fe98e9/scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4", size = 36393132, upload-time = "2025-05-08T16:08:15.34Z" }, + { url = "https://files.pythonhosted.org/packages/10/7e/5c12285452970be5bdbe8352c619250b97ebf7917d7a9a9e96b8a8140f17/scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5", size = 38979503, upload-time = "2025-05-08T16:08:21.513Z" }, + { url = "https://files.pythonhosted.org/packages/81/06/0a5e5349474e1cbc5757975b21bd4fad0e72ebf138c5592f191646154e06/scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca", size = 40308097, upload-time = "2025-05-08T16:08:27.627Z" }, +] + +[[package]] +name = "scipy" +version = "1.16.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", +] +dependencies = [ + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0a/ca/d8ace4f98322d01abcd52d381134344bf7b431eba7ed8b42bdea5a3c2ac9/scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb", size = 30597883, upload-time = "2025-10-28T17:38:54.068Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/5f/6f37d7439de1455ce9c5a556b8d1db0979f03a796c030bafdf08d35b7bf9/scipy-1.16.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:40be6cf99e68b6c4321e9f8782e7d5ff8265af28ef2cd56e9c9b2638fa08ad97", size = 36630881, upload-time = "2025-10-28T17:31:47.104Z" }, + { url = "https://files.pythonhosted.org/packages/7c/89/d70e9f628749b7e4db2aa4cd89735502ff3f08f7b9b27d2e799485987cd9/scipy-1.16.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:8be1ca9170fcb6223cc7c27f4305d680ded114a1567c0bd2bfcbf947d1b17511", size = 28941012, upload-time = "2025-10-28T17:31:53.411Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a8/0e7a9a6872a923505dbdf6bb93451edcac120363131c19013044a1e7cb0c/scipy-1.16.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:bea0a62734d20d67608660f69dcda23e7f90fb4ca20974ab80b6ed40df87a005", size = 20931935, upload-time = "2025-10-28T17:31:57.361Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c7/020fb72bd79ad798e4dbe53938543ecb96b3a9ac3fe274b7189e23e27353/scipy-1.16.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:2a207a6ce9c24f1951241f4693ede2d393f59c07abc159b2cb2be980820e01fb", size = 23534466, upload-time = "2025-10-28T17:32:01.875Z" }, + { url = "https://files.pythonhosted.org/packages/be/a0/668c4609ce6dbf2f948e167836ccaf897f95fb63fa231c87da7558a374cd/scipy-1.16.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:532fb5ad6a87e9e9cd9c959b106b73145a03f04c7d57ea3e6f6bb60b86ab0876", size = 33593618, upload-time = "2025-10-28T17:32:06.902Z" }, + { url = "https://files.pythonhosted.org/packages/ca/6e/8942461cf2636cdae083e3eb72622a7fbbfa5cf559c7d13ab250a5dbdc01/scipy-1.16.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0151a0749efeaaab78711c78422d413c583b8cdd2011a3c1d6c794938ee9fdb2", size = 35899798, upload-time = "2025-10-28T17:32:12.665Z" }, + { url = "https://files.pythonhosted.org/packages/79/e8/d0f33590364cdbd67f28ce79368b373889faa4ee959588beddf6daef9abe/scipy-1.16.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7180967113560cca57418a7bc719e30366b47959dd845a93206fbed693c867e", size = 36226154, upload-time = "2025-10-28T17:32:17.961Z" }, + { url = "https://files.pythonhosted.org/packages/39/c1/1903de608c0c924a1749c590064e65810f8046e437aba6be365abc4f7557/scipy-1.16.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:deb3841c925eeddb6afc1e4e4a45e418d19ec7b87c5df177695224078e8ec733", size = 38878540, upload-time = "2025-10-28T17:32:23.907Z" }, + { url = "https://files.pythonhosted.org/packages/f1/d0/22ec7036ba0b0a35bccb7f25ab407382ed34af0b111475eb301c16f8a2e5/scipy-1.16.3-cp311-cp311-win_amd64.whl", hash = "sha256:53c3844d527213631e886621df5695d35e4f6a75f620dca412bcd292f6b87d78", size = 38722107, upload-time = "2025-10-28T17:32:29.921Z" }, + { url = "https://files.pythonhosted.org/packages/7b/60/8a00e5a524bb3bf8898db1650d350f50e6cffb9d7a491c561dc9826c7515/scipy-1.16.3-cp311-cp311-win_arm64.whl", hash = "sha256:9452781bd879b14b6f055b26643703551320aa8d79ae064a71df55c00286a184", size = 25506272, upload-time = "2025-10-28T17:32:34.577Z" }, + { url = "https://files.pythonhosted.org/packages/40/41/5bf55c3f386b1643812f3a5674edf74b26184378ef0f3e7c7a09a7e2ca7f/scipy-1.16.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:81fc5827606858cf71446a5e98715ba0e11f0dbc83d71c7409d05486592a45d6", size = 36659043, upload-time = "2025-10-28T17:32:40.285Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0f/65582071948cfc45d43e9870bf7ca5f0e0684e165d7c9ef4e50d783073eb/scipy-1.16.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:c97176013d404c7346bf57874eaac5187d969293bf40497140b0a2b2b7482e07", size = 28898986, upload-time = "2025-10-28T17:32:45.325Z" }, + { url = "https://files.pythonhosted.org/packages/96/5e/36bf3f0ac298187d1ceadde9051177d6a4fe4d507e8f59067dc9dd39e650/scipy-1.16.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2b71d93c8a9936046866acebc915e2af2e292b883ed6e2cbe5c34beb094b82d9", size = 20889814, upload-time = "2025-10-28T17:32:49.277Z" }, + { url = "https://files.pythonhosted.org/packages/80/35/178d9d0c35394d5d5211bbff7ac4f2986c5488b59506fef9e1de13ea28d3/scipy-1.16.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3d4a07a8e785d80289dfe66b7c27d8634a773020742ec7187b85ccc4b0e7b686", size = 23565795, upload-time = "2025-10-28T17:32:53.337Z" }, + { url = "https://files.pythonhosted.org/packages/fa/46/d1146ff536d034d02f83c8afc3c4bab2eddb634624d6529a8512f3afc9da/scipy-1.16.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0553371015692a898e1aa858fed67a3576c34edefa6b7ebdb4e9dde49ce5c203", size = 33349476, upload-time = "2025-10-28T17:32:58.353Z" }, + { url = "https://files.pythonhosted.org/packages/79/2e/415119c9ab3e62249e18c2b082c07aff907a273741b3f8160414b0e9193c/scipy-1.16.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:72d1717fd3b5e6ec747327ce9bda32d5463f472c9dce9f54499e81fbd50245a1", size = 35676692, upload-time = "2025-10-28T17:33:03.88Z" }, + { url = "https://files.pythonhosted.org/packages/27/82/df26e44da78bf8d2aeaf7566082260cfa15955a5a6e96e6a29935b64132f/scipy-1.16.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fb2472e72e24d1530debe6ae078db70fb1605350c88a3d14bc401d6306dbffe", size = 36019345, upload-time = "2025-10-28T17:33:09.773Z" }, + { url = "https://files.pythonhosted.org/packages/82/31/006cbb4b648ba379a95c87262c2855cd0d09453e500937f78b30f02fa1cd/scipy-1.16.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c5192722cffe15f9329a3948c4b1db789fbb1f05c97899187dcf009b283aea70", size = 38678975, upload-time = "2025-10-28T17:33:15.809Z" }, + { url = "https://files.pythonhosted.org/packages/c2/7f/acbd28c97e990b421af7d6d6cd416358c9c293fc958b8529e0bd5d2a2a19/scipy-1.16.3-cp312-cp312-win_amd64.whl", hash = "sha256:56edc65510d1331dae01ef9b658d428e33ed48b4f77b1d51caf479a0253f96dc", size = 38555926, upload-time = "2025-10-28T17:33:21.388Z" }, + { url = "https://files.pythonhosted.org/packages/ce/69/c5c7807fd007dad4f48e0a5f2153038dc96e8725d3345b9ee31b2b7bed46/scipy-1.16.3-cp312-cp312-win_arm64.whl", hash = "sha256:a8a26c78ef223d3e30920ef759e25625a0ecdd0d60e5a8818b7513c3e5384cf2", size = 25463014, upload-time = "2025-10-28T17:33:25.975Z" }, + { url = "https://files.pythonhosted.org/packages/72/f1/57e8327ab1508272029e27eeef34f2302ffc156b69e7e233e906c2a5c379/scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c", size = 36617856, upload-time = "2025-10-28T17:33:31.375Z" }, + { url = "https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d", size = 28874306, upload-time = "2025-10-28T17:33:36.516Z" }, + { url = "https://files.pythonhosted.org/packages/15/65/3a9400efd0228a176e6ec3454b1fa998fbbb5a8defa1672c3f65706987db/scipy-1.16.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:5803c5fadd29de0cf27fa08ccbfe7a9e5d741bf63e4ab1085437266f12460ff9", size = 20865371, upload-time = "2025-10-28T17:33:42.094Z" }, + { url = "https://files.pythonhosted.org/packages/33/d7/eda09adf009a9fb81827194d4dd02d2e4bc752cef16737cc4ef065234031/scipy-1.16.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:b81c27fc41954319a943d43b20e07c40bdcd3ff7cf013f4fb86286faefe546c4", size = 23524877, upload-time = "2025-10-28T17:33:48.483Z" }, + { url = "https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959", size = 33342103, upload-time = "2025-10-28T17:33:56.495Z" }, + { url = "https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88", size = 35697297, upload-time = "2025-10-28T17:34:04.722Z" }, + { url = "https://files.pythonhosted.org/packages/04/e1/6496dadbc80d8d896ff72511ecfe2316b50313bfc3ebf07a3f580f08bd8c/scipy-1.16.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:663b8d66a8748051c3ee9c96465fb417509315b99c71550fda2591d7dd634234", size = 36021756, upload-time = "2025-10-28T17:34:13.482Z" }, + { url = "https://files.pythonhosted.org/packages/fe/bd/a8c7799e0136b987bda3e1b23d155bcb31aec68a4a472554df5f0937eef7/scipy-1.16.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eab43fae33a0c39006a88096cd7b4f4ef545ea0447d250d5ac18202d40b6611d", size = 38696566, upload-time = "2025-10-28T17:34:22.384Z" }, + { url = "https://files.pythonhosted.org/packages/cd/01/1204382461fcbfeb05b6161b594f4007e78b6eba9b375382f79153172b4d/scipy-1.16.3-cp313-cp313-win_amd64.whl", hash = "sha256:062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304", size = 38529877, upload-time = "2025-10-28T17:35:51.076Z" }, + { url = "https://files.pythonhosted.org/packages/7f/14/9d9fbcaa1260a94f4bb5b64ba9213ceb5d03cd88841fe9fd1ffd47a45b73/scipy-1.16.3-cp313-cp313-win_arm64.whl", hash = "sha256:50a3dbf286dbc7d84f176f9a1574c705f277cb6565069f88f60db9eafdbe3ee2", size = 25455366, upload-time = "2025-10-28T17:35:59.014Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a3/9ec205bd49f42d45d77f1730dbad9ccf146244c1647605cf834b3a8c4f36/scipy-1.16.3-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:fb4b29f4cf8cc5a8d628bc8d8e26d12d7278cd1f219f22698a378c3d67db5e4b", size = 37027931, upload-time = "2025-10-28T17:34:31.451Z" }, + { url = "https://files.pythonhosted.org/packages/25/06/ca9fd1f3a4589cbd825b1447e5db3a8ebb969c1eaf22c8579bd286f51b6d/scipy-1.16.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:8d09d72dc92742988b0e7750bddb8060b0c7079606c0d24a8cc8e9c9c11f9079", size = 29400081, upload-time = "2025-10-28T17:34:39.087Z" }, + { url = "https://files.pythonhosted.org/packages/6a/56/933e68210d92657d93fb0e381683bc0e53a965048d7358ff5fbf9e6a1b17/scipy-1.16.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:03192a35e661470197556de24e7cb1330d84b35b94ead65c46ad6f16f6b28f2a", size = 21391244, upload-time = "2025-10-28T17:34:45.234Z" }, + { url = "https://files.pythonhosted.org/packages/a8/7e/779845db03dc1418e215726329674b40576879b91814568757ff0014ad65/scipy-1.16.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:57d01cb6f85e34f0946b33caa66e892aae072b64b034183f3d87c4025802a119", size = 23929753, upload-time = "2025-10-28T17:34:51.793Z" }, + { url = "https://files.pythonhosted.org/packages/4c/4b/f756cf8161d5365dcdef9e5f460ab226c068211030a175d2fc7f3f41ca64/scipy-1.16.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:96491a6a54e995f00a28a3c3badfff58fd093bf26cd5fb34a2188c8c756a3a2c", size = 33496912, upload-time = "2025-10-28T17:34:59.8Z" }, + { url = "https://files.pythonhosted.org/packages/09/b5/222b1e49a58668f23839ca1542a6322bb095ab8d6590d4f71723869a6c2c/scipy-1.16.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cd13e354df9938598af2be05822c323e97132d5e6306b83a3b4ee6724c6e522e", size = 35802371, upload-time = "2025-10-28T17:35:08.173Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8d/5964ef68bb31829bde27611f8c9deeac13764589fe74a75390242b64ca44/scipy-1.16.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:63d3cdacb8a824a295191a723ee5e4ea7768ca5ca5f2838532d9f2e2b3ce2135", size = 36190477, upload-time = "2025-10-28T17:35:16.7Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f2/b31d75cb9b5fa4dd39a0a931ee9b33e7f6f36f23be5ef560bf72e0f92f32/scipy-1.16.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e7efa2681ea410b10dde31a52b18b0154d66f2485328830e45fdf183af5aefc6", size = 38796678, upload-time = "2025-10-28T17:35:26.354Z" }, + { url = "https://files.pythonhosted.org/packages/b4/1e/b3723d8ff64ab548c38d87055483714fefe6ee20e0189b62352b5e015bb1/scipy-1.16.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2d1ae2cf0c350e7705168ff2429962a89ad90c2d49d1dd300686d8b2a5af22fc", size = 38640178, upload-time = "2025-10-28T17:35:35.304Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f3/d854ff38789aca9b0cc23008d607ced9de4f7ab14fa1ca4329f86b3758ca/scipy-1.16.3-cp313-cp313t-win_arm64.whl", hash = "sha256:0c623a54f7b79dd88ef56da19bc2873afec9673a48f3b85b18e4d402bdd29a5a", size = 25803246, upload-time = "2025-10-28T17:35:42.155Z" }, + { url = "https://files.pythonhosted.org/packages/99/f6/99b10fd70f2d864c1e29a28bbcaa0c6340f9d8518396542d9ea3b4aaae15/scipy-1.16.3-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:875555ce62743e1d54f06cdf22c1e0bc47b91130ac40fe5d783b6dfa114beeb6", size = 36606469, upload-time = "2025-10-28T17:36:08.741Z" }, + { url = "https://files.pythonhosted.org/packages/4d/74/043b54f2319f48ea940dd025779fa28ee360e6b95acb7cd188fad4391c6b/scipy-1.16.3-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:bb61878c18a470021fb515a843dc7a76961a8daceaaaa8bad1332f1bf4b54657", size = 28872043, upload-time = "2025-10-28T17:36:16.599Z" }, + { url = "https://files.pythonhosted.org/packages/4d/e1/24b7e50cc1c4ee6ffbcb1f27fe9f4c8b40e7911675f6d2d20955f41c6348/scipy-1.16.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2622206f5559784fa5c4b53a950c3c7c1cf3e84ca1b9c4b6c03f062f289ca26", size = 20862952, upload-time = "2025-10-28T17:36:22.966Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3a/3e8c01a4d742b730df368e063787c6808597ccb38636ed821d10b39ca51b/scipy-1.16.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7f68154688c515cdb541a31ef8eb66d8cd1050605be9dcd74199cbd22ac739bc", size = 23508512, upload-time = "2025-10-28T17:36:29.731Z" }, + { url = "https://files.pythonhosted.org/packages/1f/60/c45a12b98ad591536bfe5330cb3cfe1850d7570259303563b1721564d458/scipy-1.16.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3c820ddb80029fe9f43d61b81d8b488d3ef8ca010d15122b152db77dc94c22", size = 33413639, upload-time = "2025-10-28T17:36:37.982Z" }, + { url = "https://files.pythonhosted.org/packages/71/bc/35957d88645476307e4839712642896689df442f3e53b0fa016ecf8a3357/scipy-1.16.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3837938ae715fc0fe3c39c0202de3a8853aff22ca66781ddc2ade7554b7e2cc", size = 35704729, upload-time = "2025-10-28T17:36:46.547Z" }, + { url = "https://files.pythonhosted.org/packages/3b/15/89105e659041b1ca11c386e9995aefacd513a78493656e57789f9d9eab61/scipy-1.16.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aadd23f98f9cb069b3bd64ddc900c4d277778242e961751f77a8cb5c4b946fb0", size = 36086251, upload-time = "2025-10-28T17:36:55.161Z" }, + { url = "https://files.pythonhosted.org/packages/1a/87/c0ea673ac9c6cc50b3da2196d860273bc7389aa69b64efa8493bdd25b093/scipy-1.16.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b7c5f1bda1354d6a19bc6af73a649f8285ca63ac6b52e64e658a5a11d4d69800", size = 38716681, upload-time = "2025-10-28T17:37:04.1Z" }, + { url = "https://files.pythonhosted.org/packages/91/06/837893227b043fb9b0d13e4bd7586982d8136cb249ffb3492930dab905b8/scipy-1.16.3-cp314-cp314-win_amd64.whl", hash = "sha256:e5d42a9472e7579e473879a1990327830493a7047506d58d73fc429b84c1d49d", size = 39358423, upload-time = "2025-10-28T17:38:20.005Z" }, + { url = "https://files.pythonhosted.org/packages/95/03/28bce0355e4d34a7c034727505a02d19548549e190bedd13a721e35380b7/scipy-1.16.3-cp314-cp314-win_arm64.whl", hash = "sha256:6020470b9d00245926f2d5bb93b119ca0340f0d564eb6fbaad843eaebf9d690f", size = 26135027, upload-time = "2025-10-28T17:38:24.966Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6f/69f1e2b682efe9de8fe9f91040f0cd32f13cfccba690512ba4c582b0bc29/scipy-1.16.3-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:e1d27cbcb4602680a49d787d90664fa4974063ac9d4134813332a8c53dbe667c", size = 37028379, upload-time = "2025-10-28T17:37:14.061Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2d/e826f31624a5ebbab1cd93d30fd74349914753076ed0593e1d56a98c4fb4/scipy-1.16.3-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9b9c9c07b6d56a35777a1b4cc8966118fb16cfd8daf6743867d17d36cfad2d40", size = 29400052, upload-time = "2025-10-28T17:37:21.709Z" }, + { url = "https://files.pythonhosted.org/packages/69/27/d24feb80155f41fd1f156bf144e7e049b4e2b9dd06261a242905e3bc7a03/scipy-1.16.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:3a4c460301fb2cffb7f88528f30b3127742cff583603aa7dc964a52c463b385d", size = 21391183, upload-time = "2025-10-28T17:37:29.559Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d3/1b229e433074c5738a24277eca520a2319aac7465eea7310ea6ae0e98ae2/scipy-1.16.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:f667a4542cc8917af1db06366d3f78a5c8e83badd56409f94d1eac8d8d9133fa", size = 23930174, upload-time = "2025-10-28T17:37:36.306Z" }, + { url = "https://files.pythonhosted.org/packages/16/9d/d9e148b0ec680c0f042581a2be79a28a7ab66c0c4946697f9e7553ead337/scipy-1.16.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f379b54b77a597aa7ee5e697df0d66903e41b9c85a6dd7946159e356319158e8", size = 33497852, upload-time = "2025-10-28T17:37:42.228Z" }, + { url = "https://files.pythonhosted.org/packages/2f/22/4e5f7561e4f98b7bea63cf3fd7934bff1e3182e9f1626b089a679914d5c8/scipy-1.16.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4aff59800a3b7f786b70bfd6ab551001cb553244988d7d6b8299cb1ea653b353", size = 35798595, upload-time = "2025-10-28T17:37:48.102Z" }, + { url = "https://files.pythonhosted.org/packages/83/42/6644d714c179429fc7196857866f219fef25238319b650bb32dde7bf7a48/scipy-1.16.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:da7763f55885045036fabcebd80144b757d3db06ab0861415d1c3b7c69042146", size = 36186269, upload-time = "2025-10-28T17:37:53.72Z" }, + { url = "https://files.pythonhosted.org/packages/ac/70/64b4d7ca92f9cf2e6fc6aaa2eecf80bb9b6b985043a9583f32f8177ea122/scipy-1.16.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d", size = 38802779, upload-time = "2025-10-28T17:37:59.393Z" }, + { url = "https://files.pythonhosted.org/packages/61/82/8d0e39f62764cce5ffd5284131e109f07cf8955aef9ab8ed4e3aa5e30539/scipy-1.16.3-cp314-cp314t-win_amd64.whl", hash = "sha256:d9f48cafc7ce94cf9b15c6bffdc443a81a27bf7075cf2dcd5c8b40f85d10c4e7", size = 39471128, upload-time = "2025-10-28T17:38:05.259Z" }, + { url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" }, +] + +[[package]] +name = "seaborn" +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "matplotlib" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "pandas" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696, upload-time = "2024-01-25T13:21:52.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, +] + +[[package]] +name = "sentence-transformers" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, + { name = "pillow" }, + { name = "scikit-learn" }, + { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "scipy", version = "1.16.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "torch" }, + { name = "tqdm" }, + { name = "transformers" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/84/b30d1b29ff58cfdff423e36a50efd622c8e31d7039b1a0d5e72066620da1/sentence_transformers-4.1.0.tar.gz", hash = "sha256:f125ffd1c727533e0eca5d4567de72f84728de8f7482834de442fd90c2c3d50b", size = 272420, upload-time = "2025-04-15T13:46:13.732Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/2d/1151b371f28caae565ad384fdc38198f1165571870217aedda230b9d7497/sentence_transformers-4.1.0-py3-none-any.whl", hash = "sha256:382a7f6be1244a100ce40495fb7523dbe8d71b3c10b299f81e6b735092b3b8ca", size = 345695, upload-time = "2025-04-15T13:46:12.44Z" }, +] + +[[package]] +name = "setuptools" +version = "80.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, +] + +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "smart-open" +version = "7.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wrapt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/1a/8de851644371c2c88ee5ff006d58355979247a02370494d63d091ef0cd01/smart_open-7.4.1.tar.gz", hash = "sha256:5c20f09026875e6dec708e9610e0cd13d24d91f0a2c12e6511b9e478a566b4a0", size = 53203, upload-time = "2025-10-21T16:28:40.075Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/ba/6dc8aea11f667b2a1455c466a42cdcd7a7efda93a1510dd085fa988c5144/smart_open-7.4.1-py3-none-any.whl", hash = "sha256:f52cb9bc897c7676dfc6996735332bd2465dfb048c73bfa9dfcdc829f48018cc", size = 63220, upload-time = "2025-10-21T16:28:38.494Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "spacy" +version = "3.8.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "catalogue" }, + { name = "cymem" }, + { name = "jinja2" }, + { name = "langcodes" }, + { name = "murmurhash" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging" }, + { name = "preshed" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "setuptools" }, + { name = "spacy-legacy" }, + { name = "spacy-loggers" }, + { name = "srsly" }, + { name = "thinc" }, + { name = "tqdm" }, + { name = "typer" }, + { name = "wasabi" }, + { name = "weasel" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1e/9e/fb4e1cefe3fbd51ea6a243e5a3d2bc629baa9a28930bf4be6fe5672fa1ca/spacy-3.8.7.tar.gz", hash = "sha256:700fd174c6c552276be142c48e70bb53cae24c4dd86003c4432af9cb93e4c908", size = 1316143, upload-time = "2025-05-23T08:55:39.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/29/2c/bbba614290492c169ee50777e44d3e4325a1e646272379988de8749b9dd4/spacy-3.8.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6ec0368ce96cd775fb14906f04b771c912ea8393ba30f8b35f9c4dc47a420b8e", size = 6613435, upload-time = "2025-05-23T08:54:03.964Z" }, + { url = "https://files.pythonhosted.org/packages/39/a9/c1fdecc11d8855b3df601bbfb5fc4cdb98d79b6a5d166af974354ea658eb/spacy-3.8.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5672f8a0fe7a3847e925544890be60015fbf48a60a838803425f82e849dd4f18", size = 6261550, upload-time = "2025-05-23T08:54:06.984Z" }, + { url = "https://files.pythonhosted.org/packages/39/fe/e8b5a374f2517716f510f0dd6a0b68e88637e66db7c315d4002ba80b2bfe/spacy-3.8.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60cde9fe8b15be04eb1e634c353d9c160187115d825b368cc1975452dd54f264", size = 31215973, upload-time = "2025-05-23T08:54:09.46Z" }, + { url = "https://files.pythonhosted.org/packages/bb/e7/bd1df17add98a5ec3e0d2dd73d4e5884683ffd2e34d3c0e5828f48933787/spacy-3.8.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cac8e58fb92fb1c5e06328039595fa6589a9d1403681266f8f5e454d15319c", size = 31504596, upload-time = "2025-05-23T08:54:12.684Z" }, + { url = "https://files.pythonhosted.org/packages/b2/fa/5fd95749f390478a31a806500e829c5a8d97312ea18129494d255e231c00/spacy-3.8.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1456245a4ed04bc882db2d89a27ca1b6dc0b947b643bedaeaa5da11d9f7e22ec", size = 30527369, upload-time = "2025-05-23T08:54:15.467Z" }, + { url = "https://files.pythonhosted.org/packages/7a/74/f4708260fc135f8de15eb1d0ecfe00fd7b53f4b1d4927f90a33d48dff637/spacy-3.8.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bb98f85d467963d17c7c660884069ba948bde71c07280c91ee3235e554375308", size = 31357330, upload-time = "2025-05-23T08:54:18.342Z" }, + { url = "https://files.pythonhosted.org/packages/53/a6/3086859d2bfb5b6f97b17e19f51da0983eb11b07f63c24dced6506cdb370/spacy-3.8.7-cp310-cp310-win_amd64.whl", hash = "sha256:b0df50d69e6691e97eae228733b321971607dbbb799e59d8470f2e70b8b27a8e", size = 14929267, upload-time = "2025-05-23T08:54:21.365Z" }, + { url = "https://files.pythonhosted.org/packages/29/c5/5fbb3a4e694d4855a5bab87af9664377c48b89691f180ad3cde4faeaf35c/spacy-3.8.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bdff8b9b556468a6dd527af17f0ddf9fb0b0bee92ee7703339ddf542361cff98", size = 6746140, upload-time = "2025-05-23T08:54:23.483Z" }, + { url = "https://files.pythonhosted.org/packages/03/2a/43afac516eb82409ca47d7206f982beaf265d2ba06a72ca07cf06b290c20/spacy-3.8.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9194b7cf015ed9b4450ffb162da49c8a9305e76b468de036b0948abdfc748a37", size = 6392440, upload-time = "2025-05-23T08:54:25.12Z" }, + { url = "https://files.pythonhosted.org/packages/6f/83/2ea68c18e2b1b9a6f6b30ef63eb9d07e979626b9595acfdb5394f18923c4/spacy-3.8.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7dc38b78d48b9c2a80a3eea95f776304993f63fc307f07cdd104441442f92f1e", size = 32699126, upload-time = "2025-05-23T08:54:27.385Z" }, + { url = "https://files.pythonhosted.org/packages/0a/0a/bb90e9aa0b3c527876627567d82517aabab08006ccf63796c33b0242254d/spacy-3.8.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e43bd70772751b8fc7a14f338d087a3d297195d43d171832923ef66204b23ab", size = 33008865, upload-time = "2025-05-23T08:54:30.248Z" }, + { url = "https://files.pythonhosted.org/packages/39/dd/8e906ba378457107ab0394976ea9f7b12fdb2cad682ef1a2ccf473d61e5f/spacy-3.8.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c402bf5dcf345fd96d202378c54bc345219681e3531f911d99567d569328c45f", size = 31933169, upload-time = "2025-05-23T08:54:33.199Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b5/42df07eb837a923fbb42509864d5c7c2072d010de933dccdfb3c655b3a76/spacy-3.8.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4234189861e486d86f1269e50542d87e8a6391a1ee190652479cf1a793db115f", size = 32776322, upload-time = "2025-05-23T08:54:36.891Z" }, + { url = "https://files.pythonhosted.org/packages/92/e7/8176484801c67dcd814f141991fe0a3c9b5b4a3583ea30c2062e93d1aa6b/spacy-3.8.7-cp311-cp311-win_amd64.whl", hash = "sha256:e9d12e2eb7f36bc11dd9edae011032fe49ea100d63e83177290d3cbd80eaa650", size = 14938936, upload-time = "2025-05-23T08:54:40.322Z" }, + { url = "https://files.pythonhosted.org/packages/a5/10/89852f40f926e0902c11c34454493ba0d15530b322711e754b89a6d7dfe6/spacy-3.8.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:88b397e37793cea51df298e6c651a763e49877a25bead5ba349761531a456687", size = 6265335, upload-time = "2025-05-23T08:54:42.876Z" }, + { url = "https://files.pythonhosted.org/packages/16/fb/b5d54522969a632c06f4af354763467553b66d5bf0671ac39f3cceb3fd54/spacy-3.8.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f70b676955fa6959347ca86ed6edd8ff0d6eb2ba20561fdfec76924bd3e540f9", size = 5906035, upload-time = "2025-05-23T08:54:44.824Z" }, + { url = "https://files.pythonhosted.org/packages/3a/03/70f06753fd65081404ade30408535eb69f627a36ffce2107116d1aa16239/spacy-3.8.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4b5a624797ade30c25b5b69daa35a93ee24bcc56bd79b0884b2565f76f35d6", size = 33420084, upload-time = "2025-05-23T08:54:46.889Z" }, + { url = "https://files.pythonhosted.org/packages/f9/19/b60e1ebf4985ee2b33d85705b89a5024942b65dad04dbdc3fb46f168b410/spacy-3.8.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9d83e006df66decccefa3872fa958b3756228fb216d83783595444cf42ca10c", size = 33922188, upload-time = "2025-05-23T08:54:49.781Z" }, + { url = "https://files.pythonhosted.org/packages/8f/a3/1fb1a49dc6d982d96fffc30c3a31bb431526008eea72ac3773f6518720a6/spacy-3.8.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0dca25deba54f3eb5dcfbf63bf16e613e6c601da56f91c4a902d38533c098941", size = 31939285, upload-time = "2025-05-23T08:54:53.162Z" }, + { url = "https://files.pythonhosted.org/packages/2d/55/6cf1aff8e5c01ee683e828f3ccd9282d2aff7ca1143a9349ee3d0c1291ff/spacy-3.8.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5eef3f805a1c118d9b709a23e2d378f5f20da5a0d6258c9cfdc87c4cb234b4fc", size = 32988845, upload-time = "2025-05-23T08:54:57.776Z" }, + { url = "https://files.pythonhosted.org/packages/8c/47/c17ee61b51aa8497d8af0999224b4b62485111a55ec105a06886685b2c68/spacy-3.8.7-cp312-cp312-win_amd64.whl", hash = "sha256:25d7a68e445200c9e9dc0044f8b7278ec0ef01ccc7cb5a95d1de2bd8e3ed6be2", size = 13918682, upload-time = "2025-05-23T08:55:00.387Z" }, + { url = "https://files.pythonhosted.org/packages/2a/95/7125bea6d432c601478bf922f7a568762c8be425bbde5b66698260ab0358/spacy-3.8.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dda7d57f42ec57c19fbef348095a9c82504e4777bca7b8db4b0d8318ba280fc7", size = 6235950, upload-time = "2025-05-23T08:55:02.92Z" }, + { url = "https://files.pythonhosted.org/packages/96/c3/d2362846154d4d341136774831605df02d61f49ac637524a15f4f2794874/spacy-3.8.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:de0e0bddb810ed05bce44bcb91460eabe52bc56323da398d2ca74288a906da35", size = 5878106, upload-time = "2025-05-23T08:55:04.496Z" }, + { url = "https://files.pythonhosted.org/packages/50/b6/b2943acfbfc4fc12642dac9feb571e712dd1569ab481db8f3daedee045fe/spacy-3.8.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a2e58f92b684465777a7c1a65d5578b1dc36fe55c48d9964fb6d46cc9449768", size = 33085866, upload-time = "2025-05-23T08:55:06.65Z" }, + { url = "https://files.pythonhosted.org/packages/65/98/c4415cbb217ac0b502dbb3372136015c699dd16a0c47cd6d338cd15f4bed/spacy-3.8.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46330da2eb357d6979f40ea8fc16ee5776ee75cd0c70aac2a4ea10c80364b8f3", size = 33398424, upload-time = "2025-05-23T08:55:10.477Z" }, + { url = "https://files.pythonhosted.org/packages/12/45/12a198858f1f11c21844876e039ba90df59d550527c72996d418c1faf78d/spacy-3.8.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:86b6a6ad23ca5440ef9d29c2b1e3125e28722c927db612ae99e564d49202861c", size = 31530066, upload-time = "2025-05-23T08:55:13.329Z" }, + { url = "https://files.pythonhosted.org/packages/9c/df/80524f99822eb96c9649200042ec5912357eec100cf0cd678a2e9ef0ecb3/spacy-3.8.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ccfe468cbb370888153df145ce3693af8e54dae551940df49057258081b2112f", size = 32613343, upload-time = "2025-05-23T08:55:16.711Z" }, + { url = "https://files.pythonhosted.org/packages/02/99/881f6f24c279a5a70b8d69aaf8266fd411a0a58fd1c8848112aaa348f6f6/spacy-3.8.7-cp313-cp313-win_amd64.whl", hash = "sha256:ca81e416ff35209769e8b5dd5d13acc52e4f57dd9d028364bccbbe157c2ae86b", size = 13911250, upload-time = "2025-05-23T08:55:19.606Z" }, +] + +[[package]] +name = "spacy-legacy" +version = "3.0.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/79/91f9d7cc8db5642acad830dcc4b49ba65a7790152832c4eceb305e46d681/spacy-legacy-3.0.12.tar.gz", hash = "sha256:b37d6e0c9b6e1d7ca1cf5bc7152ab64a4c4671f59c85adaf7a3fcb870357a774", size = 23806, upload-time = "2023-01-23T09:04:15.104Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/55/12e842c70ff8828e34e543a2c7176dac4da006ca6901c9e8b43efab8bc6b/spacy_legacy-3.0.12-py2.py3-none-any.whl", hash = "sha256:476e3bd0d05f8c339ed60f40986c07387c0a71479245d6d0f4298dbd52cda55f", size = 29971, upload-time = "2023-01-23T09:04:13.45Z" }, +] + +[[package]] +name = "spacy-loggers" +version = "1.0.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/67/3d/926db774c9c98acf66cb4ed7faf6c377746f3e00b84b700d0868b95d0712/spacy-loggers-1.0.5.tar.gz", hash = "sha256:d60b0bdbf915a60e516cc2e653baeff946f0cfc461b452d11a4d5458c6fe5f24", size = 20811, upload-time = "2023-09-11T12:26:52.323Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/78/d1a1a026ef3af911159398c939b1509d5c36fe524c7b644f34a5146c4e16/spacy_loggers-1.0.5-py3-none-any.whl", hash = "sha256:196284c9c446cc0cdb944005384270d775fdeaf4f494d8e269466cfa497ef645", size = 22343, upload-time = "2023-09-11T12:26:50.586Z" }, +] + +[[package]] +name = "srsly" +version = "2.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "catalogue" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b7/e8/eb51b1349f50bac0222398af0942613fdc9d1453ae67cbe4bf9936a1a54b/srsly-2.5.1.tar.gz", hash = "sha256:ab1b4bf6cf3e29da23dae0493dd1517fb787075206512351421b89b4fc27c77e", size = 466464, upload-time = "2025-01-17T09:26:26.919Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/08/448bcc87bb93bc19fccf70c2f0f993ac42aa41d5f44a19c60d00186aea09/srsly-2.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d0cda6f65cc0dd1daf47e856b0d6c5d51db8a9343c5007723ca06903dcfe367d", size = 636045, upload-time = "2025-01-17T09:25:04.605Z" }, + { url = "https://files.pythonhosted.org/packages/03/8a/379dd9014e56460e71346cf512632fb8cbc89aa6dfebe31dff21c9eb37ba/srsly-2.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf643e6f45c266cfacea54997a1f9cfe0113fadac1ac21a1ec5b200cfe477ba0", size = 634425, upload-time = "2025-01-17T09:25:07.957Z" }, + { url = "https://files.pythonhosted.org/packages/95/69/46e672941b5f4403b0e2b14918d8e1393ca48e3338e2c01e549113261cdf/srsly-2.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:467ed25ddab09ca9404fda92519a317c803b5ea0849f846e74ba8b7843557df5", size = 1085032, upload-time = "2025-01-17T09:25:11.291Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d8/1039e663b87a06d2450148ebadc07eaf6f8b7dd7f7d5e2f4221050ce6702/srsly-2.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f8113d202664b7d31025bdbe40b9d3536e8d7154d09520b6a1955818fa6d622", size = 1089469, upload-time = "2025-01-17T09:25:15.913Z" }, + { url = "https://files.pythonhosted.org/packages/e9/62/f819ac665ecca2659343a6c79174c582fe292829f481899f05e7a7301988/srsly-2.5.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:794d39fccd2b333d24f1b445acc78daf90f3f37d3c0f6f0167f25c56961804e7", size = 1052673, upload-time = "2025-01-17T09:25:17.658Z" }, + { url = "https://files.pythonhosted.org/packages/a8/69/321a41fe4d549b96dd010b6a77657e84eb181034f9d125e2feebcd8f2e5c/srsly-2.5.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:df7fd77457c4d6c630f700b1019a8ad173e411e7cf7cfdea70e5ed86b608083b", size = 1062650, upload-time = "2025-01-17T09:25:20.704Z" }, + { url = "https://files.pythonhosted.org/packages/d5/b8/3dfed2db5c7ecf275aaddb775e2ae17c576b09c848873188fce91e410129/srsly-2.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:1a4dddb2edb8f7974c9aa5ec46dc687a75215b3bbdc815ce3fc9ea68fe1e94b5", size = 632267, upload-time = "2025-01-17T09:25:23.713Z" }, + { url = "https://files.pythonhosted.org/packages/df/9c/a248bb49de499fe0990e3cb0fb341c2373d8863ef9a8b5799353cade5731/srsly-2.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58f0736794ce00a71d62a39cbba1d62ea8d5be4751df956e802d147da20ecad7", size = 635917, upload-time = "2025-01-17T09:25:25.109Z" }, + { url = "https://files.pythonhosted.org/packages/41/47/1bdaad84502df973ecb8ca658117234cf7fb20e1dec60da71dce82de993f/srsly-2.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a8269c40859806d71920396d185f4f38dc985cdb6a28d3a326a701e29a5f629", size = 634374, upload-time = "2025-01-17T09:25:26.609Z" }, + { url = "https://files.pythonhosted.org/packages/e5/2a/d73c71989fcf2a6d1fa518d75322aff4db01a8763f167f8c5e00aac11097/srsly-2.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:889905900401fefc1032e22b73aecbed8b4251aa363f632b2d1f86fc16f1ad8e", size = 1108390, upload-time = "2025-01-17T09:25:29.32Z" }, + { url = "https://files.pythonhosted.org/packages/35/a3/9eda9997a8bd011caed18fdaa5ce606714eb06d8dab587ed0522b3e92ab1/srsly-2.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf454755f22589df49c25dc799d8af7b47dce3d861dded35baf0f0b6ceab4422", size = 1110712, upload-time = "2025-01-17T09:25:31.051Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ef/4b50bc05d06349f905b27f824cc23b652098efd4be19aead3af4981df647/srsly-2.5.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cc0607c8a59013a51dde5c1b4e465558728e9e0a35dcfa73c7cbefa91a0aad50", size = 1081244, upload-time = "2025-01-17T09:25:32.611Z" }, + { url = "https://files.pythonhosted.org/packages/90/af/d4a2512d9a5048d2b18efead39d4c4404bddd4972935bbc68211292a736c/srsly-2.5.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d5421ba3ab3c790e8b41939c51a1d0f44326bfc052d7a0508860fb79a47aee7f", size = 1091692, upload-time = "2025-01-17T09:25:34.15Z" }, + { url = "https://files.pythonhosted.org/packages/bb/da/657a685f63028dcb00ccdc4ac125ed347c8bff6fa0dab6a9eb3dc45f3223/srsly-2.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:b96ea5a9a0d0379a79c46d255464a372fb14c30f59a8bc113e4316d131a530ab", size = 632627, upload-time = "2025-01-17T09:25:37.36Z" }, + { url = "https://files.pythonhosted.org/packages/fb/f6/bebc20d75bd02121fc0f65ad8c92a5dd2570e870005e940faa55a263e61a/srsly-2.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:683b54ed63d7dfee03bc2abc4b4a5f2152f81ec217bbadbac01ef1aaf2a75790", size = 636717, upload-time = "2025-01-17T09:25:40.236Z" }, + { url = "https://files.pythonhosted.org/packages/b6/e8/9372317a4742c70b87b413335adfcdfb2bee4f88f3faba89fabb9e6abf21/srsly-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:459d987130e57e83ce9e160899afbeb871d975f811e6958158763dd9a8a20f23", size = 634697, upload-time = "2025-01-17T09:25:43.605Z" }, + { url = "https://files.pythonhosted.org/packages/d5/00/c6a7b99ab27b051a27bd26fe1a8c1885225bb8980282bf9cb99f70610368/srsly-2.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:184e3c98389aab68ff04aab9095bd5f1a8e5a72cc5edcba9d733bac928f5cf9f", size = 1134655, upload-time = "2025-01-17T09:25:45.238Z" }, + { url = "https://files.pythonhosted.org/packages/c2/e6/861459e8241ec3b78c111081bd5efa414ef85867e17c45b6882954468d6e/srsly-2.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c2a3e4856e63b7efd47591d049aaee8e5a250e098917f50d93ea68853fab78", size = 1143544, upload-time = "2025-01-17T09:25:47.485Z" }, + { url = "https://files.pythonhosted.org/packages/2d/85/8448fe874dd2042a4eceea5315cfff3af03ac77ff5073812071852c4e7e2/srsly-2.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:366b4708933cd8d6025c13c2cea3331f079c7bb5c25ec76fca392b6fc09818a0", size = 1098330, upload-time = "2025-01-17T09:25:52.55Z" }, + { url = "https://files.pythonhosted.org/packages/ef/7e/04d0e1417da140b2ac4053a3d4fcfc86cd59bf4829f69d370bb899f74d5d/srsly-2.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c8a0b03c64eb6e150d772c5149befbadd981cc734ab13184b0561c17c8cef9b1", size = 1110670, upload-time = "2025-01-17T09:25:54.02Z" }, + { url = "https://files.pythonhosted.org/packages/96/1a/a8cd627eaa81a91feb6ceab50155f4ceff3eef6107916cb87ef796958427/srsly-2.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:7952538f6bba91b9d8bf31a642ac9e8b9ccc0ccbb309feb88518bfb84bb0dc0d", size = 632598, upload-time = "2025-01-17T09:25:55.499Z" }, + { url = "https://files.pythonhosted.org/packages/42/94/cab36845aad6e2c22ecee1178accaa365657296ff87305b805648fd41118/srsly-2.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84b372f7ef1604b4a5b3cee1571993931f845a5b58652ac01bcb32c52586d2a8", size = 634883, upload-time = "2025-01-17T09:25:58.363Z" }, + { url = "https://files.pythonhosted.org/packages/67/8b/501f51f4eaee7e1fd7327764799cb0a42f5d0de042a97916d30dbff770fc/srsly-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6ac3944c112acb3347a39bfdc2ebfc9e2d4bace20fe1c0b764374ac5b83519f2", size = 632842, upload-time = "2025-01-17T09:25:59.777Z" }, + { url = "https://files.pythonhosted.org/packages/07/be/5b8fce4829661e070a7d3e262d2e533f0e297b11b8993d57240da67d7330/srsly-2.5.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6118f9c4b221cde0a990d06a42c8a4845218d55b425d8550746fe790acf267e9", size = 1118516, upload-time = "2025-01-17T09:26:01.234Z" }, + { url = "https://files.pythonhosted.org/packages/91/60/a34e97564eac352c0e916c98f44b6f566b7eb6a9fb60bcd60ffa98530762/srsly-2.5.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7481460110d9986781d9e4ac0f5f991f1d6839284a80ad268625f9a23f686950", size = 1127974, upload-time = "2025-01-17T09:26:04.007Z" }, + { url = "https://files.pythonhosted.org/packages/70/a2/f642334db0cabd187fa86b8773257ee6993c6009338a6831d4804e2c5b3c/srsly-2.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e57b8138082f09e35db60f99757e16652489e9e3692471d8e0c39aa95180688", size = 1086098, upload-time = "2025-01-17T09:26:05.612Z" }, + { url = "https://files.pythonhosted.org/packages/0d/9b/be48e185c5a010e71b5135e4cdf317ff56b8ac4bc08f394bbf882ac13b05/srsly-2.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bab90b85a63a1fe0bbc74d373c8bb9bb0499ddfa89075e0ebe8d670f12d04691", size = 1100354, upload-time = "2025-01-17T09:26:07.215Z" }, + { url = "https://files.pythonhosted.org/packages/3a/e2/745aeba88a8513017fbac2fd2f9f07b8a36065e51695f818541eb795ec0c/srsly-2.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:e73712be1634b5e1de6f81c273a7d47fe091ad3c79dc779c03d3416a5c117cee", size = 630634, upload-time = "2025-01-17T09:26:10.018Z" }, +] + +[[package]] +name = "sympy" +version = "1.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mpmath" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921, upload-time = "2025-04-27T18:05:01.611Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353, upload-time = "2025-04-27T18:04:59.103Z" }, +] + +[[package]] +name = "thinc" +version = "8.3.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "blis" }, + { name = "catalogue" }, + { name = "confection" }, + { name = "cymem" }, + { name = "murmurhash" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging" }, + { name = "preshed" }, + { name = "pydantic" }, + { name = "setuptools" }, + { name = "srsly" }, + { name = "wasabi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/f4/7607f76c2e156a34b1961a941eb8407b84da4f515cc0903b44d44edf4f45/thinc-8.3.6.tar.gz", hash = "sha256:49983f9b7ddc4343a9532694a9118dd216d7a600520a21849a43b6c268ec6cad", size = 194218, upload-time = "2025-04-04T11:50:45.751Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/36/92233344b30caab56c2d8b0fc92472ec37402a5088f4f89ced96821e1638/thinc-8.3.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f4abec5a35e5945a6573b62bf0f423709467ba321fea9d00770b4c5282a8257d", size = 894690, upload-time = "2025-04-04T11:49:38.682Z" }, + { url = "https://files.pythonhosted.org/packages/e9/7e/ce6acadb3ae92836ed9eef2359fd2bd5f9257d22c422b44dd9c1cbc2b5c8/thinc-8.3.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba7ced4bfc5890dd8f4be2978f8d491a07e80c9d9a7fffae9f57970b55db01bd", size = 844882, upload-time = "2025-04-04T11:49:45.947Z" }, + { url = "https://files.pythonhosted.org/packages/9d/88/26ca6b5d097d7958451fb4f6e67bcce6dfe31e73f21c16fd905315806f2a/thinc-8.3.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e645517d87f71e92137a1aef028094d134223885e15b8472bfcdc09665973ed", size = 4072032, upload-time = "2025-04-04T11:49:47.636Z" }, + { url = "https://files.pythonhosted.org/packages/c0/eb/12681892dbcaa45eedeb37dcf40251ea47e22e97413e6d4209fa4db2b9f2/thinc-8.3.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d8451dd08386d6bbde8160fd0e5e057e04a330c168837d3e0f278fa8738eea", size = 4136573, upload-time = "2025-04-04T11:49:49.106Z" }, + { url = "https://files.pythonhosted.org/packages/5f/76/98dd4983efbd7eebdd5d5964c566c8e5c10782db1599fc694610ba49ba75/thinc-8.3.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0e913f120fde25aea9f052e8cd45dd9cd36553ff1903e312b7302dd91000125a", size = 4949592, upload-time = "2025-04-04T11:49:50.64Z" }, + { url = "https://files.pythonhosted.org/packages/cd/7f/d867c7bcb22cd6022d9931f625340b26e86fd9cf25905adc408bc7393799/thinc-8.3.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:03706680bc0ea92036ac2e00f46bc86116ac6dccb6212b0c632e835176f666b2", size = 5165689, upload-time = "2025-04-04T11:49:52.385Z" }, + { url = "https://files.pythonhosted.org/packages/ed/8c/d6000d6d19cc1fc800ceb073b44403ce27a3414248cede691b5c49cbfb22/thinc-8.3.6-cp310-cp310-win_amd64.whl", hash = "sha256:0902314ecb83a225f41ab6121ceaf139b5da8bb6ada9e58031bad6c46134b8d4", size = 1773832, upload-time = "2025-04-04T11:49:54.259Z" }, + { url = "https://files.pythonhosted.org/packages/23/b4/b4ed217679327849ad796dc8ced307447a05e9f607bb12f290b2ec99fb35/thinc-8.3.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7c7c44f8736f27d1cced216246c00e219fb5734e6bc3b8a78c09157c011aae59", size = 895694, upload-time = "2025-04-04T11:49:56.102Z" }, + { url = "https://files.pythonhosted.org/packages/f0/53/5f9eeb725c2ca94adef76a2cd0289bc530728b0a035eed815c766a9291ef/thinc-8.3.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:92b3c38bdfdf81d0485685a6261b8a6ea40e03120b08ced418c8400f5e186b2d", size = 845256, upload-time = "2025-04-04T11:49:57.401Z" }, + { url = "https://files.pythonhosted.org/packages/89/8e/fae78ba63b1b0fb9017fd51d0aeffdc22e837807a93d55100c92e6d30570/thinc-8.3.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853eb187b1f77057adada1a72e7f6ea3f38643930363681cfd5de285dab4b09b", size = 4402142, upload-time = "2025-04-04T11:49:59.144Z" }, + { url = "https://files.pythonhosted.org/packages/ae/7e/6b1bb6eba9c25a5911e1624c0da33ca007d7697b41ee11c059f3d23d8bbc/thinc-8.3.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c12bf75a375b3b1f7c32a26cbd69255b177daa693c986a27faaf2027439c7ef", size = 4463797, upload-time = "2025-04-04T11:50:00.647Z" }, + { url = "https://files.pythonhosted.org/packages/42/39/c5f48785f76cd97a79e83b1acd3dab7d0835e4b560c9d7add846b47ea984/thinc-8.3.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5bf1708c22fb54e7846e8e743a9e6a43a22cbe24cab0081ba4e6362b4437a53f", size = 5313270, upload-time = "2025-04-04T11:50:02.241Z" }, + { url = "https://files.pythonhosted.org/packages/a3/32/ce8e7827ed0a1f86eab864e6b0b8ae79118e4e5c40ffd8b21938f8961e23/thinc-8.3.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:169d7c5779f6f1a78fa91b2bc3a6485f7bbe4341bd8064576f8e067b67b6a0b5", size = 5508338, upload-time = "2025-04-04T11:50:04.18Z" }, + { url = "https://files.pythonhosted.org/packages/94/40/7e5e840ac2e835fbf5d87e3ab94df7d678d846aaf28b12d46538ed36bf7f/thinc-8.3.6-cp311-cp311-win_amd64.whl", hash = "sha256:59c244ce11a3359b9a33b4c3bbc9ba94f7174214356ed88c16a41e39f31fe372", size = 1775998, upload-time = "2025-04-04T11:50:05.744Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c8/a9250944fb9a0a4c65b5d456f3a87ee6c249b53962757d77c28df8fadb46/thinc-8.3.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c54705e45a710e49758192592a3e0a80482edfdf5c61fc99f5d27ae822f652c5", size = 890177, upload-time = "2025-04-04T11:50:07.543Z" }, + { url = "https://files.pythonhosted.org/packages/3b/89/1ac54b18d4de79872c633302a10825695a36cd2e552cb8d4fea820b7a357/thinc-8.3.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:91acdbf3041c0ac1775ede570535a779cdf1312c317cd054d7b9d200da685c23", size = 839410, upload-time = "2025-04-04T11:50:09.26Z" }, + { url = "https://files.pythonhosted.org/packages/37/76/e1a76ab42e4637c4b8988d59784cdc1169a532d3043c36d2faf1a8d95228/thinc-8.3.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5a1db861614f91ff127feecce681c2213777b2d3d1ee6644bcc8a886acf0595", size = 4195748, upload-time = "2025-04-04T11:50:10.92Z" }, + { url = "https://files.pythonhosted.org/packages/00/a9/c59ac3260e7aff6b9dc80f495f1846a80b490595db06d040b05205d1f7f8/thinc-8.3.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:512e461989df8a30558367061d63ae6f1a6b4abe3c016a3360ee827e824254e0", size = 4261270, upload-time = "2025-04-04T11:50:12.953Z" }, + { url = "https://files.pythonhosted.org/packages/e0/8e/e86c5cbc6ebe238aa747ef9e20a969f6faba9ebbe1cbce059119f9614dd6/thinc-8.3.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a087aea2a63e6b9ccde61163d5922553b58908e96f8ad49cd0fd2edeb43e063f", size = 5067567, upload-time = "2025-04-04T11:50:18.317Z" }, + { url = "https://files.pythonhosted.org/packages/fe/8a/16670e4de36231aab5b052c734ad716be29aab2c0d2f3d8dd9c8dd27fafc/thinc-8.3.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b1d85dd5d94bb75006864c7d99fd5b75d05b1602d571e7fcdb42d4521f962048", size = 5309405, upload-time = "2025-04-04T11:50:20.075Z" }, + { url = "https://files.pythonhosted.org/packages/58/08/5439dd15b661610d8a3b919f18065ebf0d664b6a54a3794206622a74c910/thinc-8.3.6-cp312-cp312-win_amd64.whl", hash = "sha256:1170d85294366127d97a27dd5896f4abe90e2a5ea2b7988de9a5bb8e1128d222", size = 1749275, upload-time = "2025-04-04T11:50:21.769Z" }, + { url = "https://files.pythonhosted.org/packages/a6/03/0ba9bec3057f4a9c0b7ba53839aebcbbbc28de3b91330cb8de74a885b8f6/thinc-8.3.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d8743ee8ad2d59fda018b57e5da102d6098bbeb0f70476f3fd8ceb9d215d88b9", size = 883375, upload-time = "2025-04-04T11:50:23.273Z" }, + { url = "https://files.pythonhosted.org/packages/ae/79/ac31cd25d1d973b824de10ebbc56788688aecdd8f56800daf8edfff45097/thinc-8.3.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:89dbeb2ca94f1033e90999a70e2bc9dd5390d5341dc1a3a4b8793d03855265c3", size = 832654, upload-time = "2025-04-04T11:50:24.871Z" }, + { url = "https://files.pythonhosted.org/packages/f8/0d/fb5e8e49dfb53cc02ce907f81002031c6f4fe7e7aa44b1004ea695630017/thinc-8.3.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89a5460695067aa6e4182515cfd2018263db77cc17b7031d50ed696e990797a8", size = 4158592, upload-time = "2025-04-04T11:50:26.403Z" }, + { url = "https://files.pythonhosted.org/packages/e5/42/c87990ca214b9910f33b110d3b1ac213407388d35376bc955ad45e5de764/thinc-8.3.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0aa8e32f49234569fd10c35b562ee2f9c0d51225365a6e604a5a67396a49f2c1", size = 4236211, upload-time = "2025-04-04T11:50:27.943Z" }, + { url = "https://files.pythonhosted.org/packages/fa/10/9975bcee4dd4634bfb87df0447d7fa86d6c9b2d9228e56d4adb98cc19cbc/thinc-8.3.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f432158b80cf75a096980470b790b51d81daf9c2822598adebfc3cb58588fd6c", size = 5049197, upload-time = "2025-04-04T11:50:29.583Z" }, + { url = "https://files.pythonhosted.org/packages/9b/34/e1b384009eb8ad2192770157961cd0c2e2712fedf49e1dfd902e3d9b9973/thinc-8.3.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:61fb33a22aba40366fa9018ab34580f74fc40be821ab8af77ac1fdbeac17243b", size = 5278543, upload-time = "2025-04-04T11:50:31.524Z" }, + { url = "https://files.pythonhosted.org/packages/f0/26/f77ef4bd174bfeac491237a4ca3f74ba2ee2f672004f76cff90f8407a489/thinc-8.3.6-cp313-cp313-win_amd64.whl", hash = "sha256:ddd7041946a427f6a9b0b49419353d02ad7eb43fe16724bfcc3bdeb9562040b1", size = 1746883, upload-time = "2025-04-04T11:50:33.038Z" }, +] + +[[package]] +name = "threadpoolctl" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, +] + +[[package]] +name = "tokenizers" +version = "0.21.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/2f/402986d0823f8d7ca139d969af2917fefaa9b947d1fb32f6168c509f2492/tokenizers-0.21.4.tar.gz", hash = "sha256:fa23f85fbc9a02ec5c6978da172cdcbac23498c3ca9f3645c5c68740ac007880", size = 351253, upload-time = "2025-07-28T15:48:54.325Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/c6/fdb6f72bf6454f52eb4a2510be7fb0f614e541a2554d6210e370d85efff4/tokenizers-0.21.4-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:2ccc10a7c3bcefe0f242867dc914fc1226ee44321eb618cfe3019b5df3400133", size = 2863987, upload-time = "2025-07-28T15:48:44.877Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a6/28975479e35ddc751dc1ddc97b9b69bf7fcf074db31548aab37f8116674c/tokenizers-0.21.4-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:5e2f601a8e0cd5be5cc7506b20a79112370b9b3e9cb5f13f68ab11acd6ca7d60", size = 2732457, upload-time = "2025-07-28T15:48:43.265Z" }, + { url = "https://files.pythonhosted.org/packages/aa/8f/24f39d7b5c726b7b0be95dca04f344df278a3fe3a4deb15a975d194cbb32/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b376f5a1aee67b4d29032ee85511bbd1b99007ec735f7f35c8a2eb104eade5", size = 3012624, upload-time = "2025-07-28T13:22:43.895Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/26358925717687a58cb74d7a508de96649544fad5778f0cd9827398dc499/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2107ad649e2cda4488d41dfd031469e9da3fcbfd6183e74e4958fa729ffbf9c6", size = 2939681, upload-time = "2025-07-28T13:22:47.499Z" }, + { url = "https://files.pythonhosted.org/packages/99/6f/cc300fea5db2ab5ddc2c8aea5757a27b89c84469899710c3aeddc1d39801/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c73012da95afafdf235ba80047699df4384fdc481527448a078ffd00e45a7d9", size = 3247445, upload-time = "2025-07-28T15:48:39.711Z" }, + { url = "https://files.pythonhosted.org/packages/be/bf/98cb4b9c3c4afd8be89cfa6423704337dc20b73eb4180397a6e0d456c334/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f23186c40395fc390d27f519679a58023f368a0aad234af145e0f39ad1212732", size = 3428014, upload-time = "2025-07-28T13:22:49.569Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/96c1cc780e6ca7f01a57c13235dd05b7bc1c0f3588512ebe9d1331b5f5ae/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc88bb34e23a54cc42713d6d98af5f1bf79c07653d24fe984d2d695ba2c922a2", size = 3193197, upload-time = "2025-07-28T13:22:51.471Z" }, + { url = "https://files.pythonhosted.org/packages/f2/90/273b6c7ec78af547694eddeea9e05de771278bd20476525ab930cecaf7d8/tokenizers-0.21.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51b7eabb104f46c1c50b486520555715457ae833d5aee9ff6ae853d1130506ff", size = 3115426, upload-time = "2025-07-28T15:48:41.439Z" }, + { url = "https://files.pythonhosted.org/packages/91/43/c640d5a07e95f1cf9d2c92501f20a25f179ac53a4f71e1489a3dcfcc67ee/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:714b05b2e1af1288bd1bc56ce496c4cebb64a20d158ee802887757791191e6e2", size = 9089127, upload-time = "2025-07-28T15:48:46.472Z" }, + { url = "https://files.pythonhosted.org/packages/44/a1/dd23edd6271d4dca788e5200a807b49ec3e6987815cd9d0a07ad9c96c7c2/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:1340ff877ceedfa937544b7d79f5b7becf33a4cfb58f89b3b49927004ef66f78", size = 9055243, upload-time = "2025-07-28T15:48:48.539Z" }, + { url = "https://files.pythonhosted.org/packages/21/2b/b410d6e9021c4b7ddb57248304dc817c4d4970b73b6ee343674914701197/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:3c1f4317576e465ac9ef0d165b247825a2a4078bcd01cba6b54b867bdf9fdd8b", size = 9298237, upload-time = "2025-07-28T15:48:50.443Z" }, + { url = "https://files.pythonhosted.org/packages/b7/0a/42348c995c67e2e6e5c89ffb9cfd68507cbaeb84ff39c49ee6e0a6dd0fd2/tokenizers-0.21.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:c212aa4e45ec0bb5274b16b6f31dd3f1c41944025c2358faaa5782c754e84c24", size = 9461980, upload-time = "2025-07-28T15:48:52.325Z" }, + { url = "https://files.pythonhosted.org/packages/3d/d3/dacccd834404cd71b5c334882f3ba40331ad2120e69ded32cf5fda9a7436/tokenizers-0.21.4-cp39-abi3-win32.whl", hash = "sha256:6c42a930bc5f4c47f4ea775c91de47d27910881902b0f20e4990ebe045a415d0", size = 2329871, upload-time = "2025-07-28T15:48:56.841Z" }, + { url = "https://files.pythonhosted.org/packages/41/f2/fd673d979185f5dcbac4be7d09461cbb99751554ffb6718d0013af8604cb/tokenizers-0.21.4-cp39-abi3-win_amd64.whl", hash = "sha256:475d807a5c3eb72c59ad9b5fcdb254f6e17f53dfcbb9903233b0dfa9c943b597", size = 2507568, upload-time = "2025-07-28T15:48:55.456Z" }, +] + +[[package]] +name = "tomli" +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/de/48c59722572767841493b26183a0d1cc411d54fd759c5607c4590b6563a6/tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f", size = 17543, upload-time = "2026-03-25T20:22:03.828Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/11/db3d5885d8528263d8adc260bb2d28ebf1270b96e98f0e0268d32b8d9900/tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30", size = 154704, upload-time = "2026-03-25T20:21:10.473Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f7/675db52c7e46064a9aa928885a9b20f4124ecb9bc2e1ce74c9106648d202/tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a", size = 149454, upload-time = "2026-03-25T20:21:12.036Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/81c50943cf953efa35bce7646caab3cf457a7d8c030b27cfb40d7235f9ee/tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076", size = 237561, upload-time = "2026-03-25T20:21:13.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/c1/f41d9cb618acccca7df82aaf682f9b49013c9397212cb9f53219e3abac37/tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9", size = 243824, upload-time = "2026-03-25T20:21:14.569Z" }, + { url = "https://files.pythonhosted.org/packages/22/e4/5a816ecdd1f8ca51fb756ef684b90f2780afc52fc67f987e3c61d800a46d/tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c", size = 242227, upload-time = "2026-03-25T20:21:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/6b/49/2b2a0ef529aa6eec245d25f0c703e020a73955ad7edf73e7f54ddc608aa5/tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc", size = 247859, upload-time = "2026-03-25T20:21:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/83/bd/6c1a630eaca337e1e78c5903104f831bda934c426f9231429396ce3c3467/tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049", size = 97204, upload-time = "2026-03-25T20:21:18.079Z" }, + { url = "https://files.pythonhosted.org/packages/42/59/71461df1a885647e10b6bb7802d0b8e66480c61f3f43079e0dcd315b3954/tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e", size = 108084, upload-time = "2026-03-25T20:21:18.978Z" }, + { url = "https://files.pythonhosted.org/packages/b8/83/dceca96142499c069475b790e7913b1044c1a4337e700751f48ed723f883/tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece", size = 95285, upload-time = "2026-03-25T20:21:20.309Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ba/42f134a3fe2b370f555f44b1d72feebb94debcab01676bf918d0cb70e9aa/tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a", size = 155924, upload-time = "2026-03-25T20:21:21.626Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c7/62d7a17c26487ade21c5422b646110f2162f1fcc95980ef7f63e73c68f14/tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085", size = 150018, upload-time = "2026-03-25T20:21:23.002Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/79d13d7c15f13bdef410bdd49a6485b1c37d28968314eabee452c22a7fda/tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9", size = 244948, upload-time = "2026-03-25T20:21:24.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/90/d62ce007a1c80d0b2c93e02cab211224756240884751b94ca72df8a875ca/tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5", size = 253341, upload-time = "2026-03-25T20:21:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/caf6496d60152ad4ed09282c1885cca4eea150bfd007da84aea07bcc0a3e/tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585", size = 248159, upload-time = "2026-03-25T20:21:26.364Z" }, + { url = "https://files.pythonhosted.org/packages/99/e7/c6f69c3120de34bbd882c6fba7975f3d7a746e9218e56ab46a1bc4b42552/tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1", size = 253290, upload-time = "2026-03-25T20:21:27.46Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2f/4a3c322f22c5c66c4b836ec58211641a4067364f5dcdd7b974b4c5da300c/tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917", size = 98141, upload-time = "2026-03-25T20:21:28.492Z" }, + { url = "https://files.pythonhosted.org/packages/24/22/4daacd05391b92c55759d55eaee21e1dfaea86ce5c571f10083360adf534/tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9", size = 108847, upload-time = "2026-03-25T20:21:29.386Z" }, + { url = "https://files.pythonhosted.org/packages/68/fd/70e768887666ddd9e9f5d85129e84910f2db2796f9096aa02b721a53098d/tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257", size = 95088, upload-time = "2026-03-25T20:21:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/b823a7e818c756d9a7123ba2cda7d07bc2dd32835648d1a7b7b7a05d848d/tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54", size = 155866, upload-time = "2026-03-25T20:21:31.65Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/12645cf7f08e1a20c7eb8c297c6f11d31c1b50f316a7e7e1e1de6e2e7b7e/tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a", size = 149887, upload-time = "2026-03-25T20:21:33.028Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/90637574e5e7212c09099c67ad349b04ec4d6020324539297b634a0192b0/tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897", size = 243704, upload-time = "2026-03-25T20:21:34.51Z" }, + { url = "https://files.pythonhosted.org/packages/10/8f/d3ddb16c5a4befdf31a23307f72828686ab2096f068eaf56631e136c1fdd/tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f", size = 251628, upload-time = "2026-03-25T20:21:36.012Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f1/dbeeb9116715abee2485bf0a12d07a8f31af94d71608c171c45f64c0469d/tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d", size = 247180, upload-time = "2026-03-25T20:21:37.136Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/16336ffd19ed4da28a70959f92f506233bd7cfc2332b20bdb01591e8b1d1/tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5", size = 251674, upload-time = "2026-03-25T20:21:38.298Z" }, + { url = "https://files.pythonhosted.org/packages/16/f9/229fa3434c590ddf6c0aa9af64d3af4b752540686cace29e6281e3458469/tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd", size = 97976, upload-time = "2026-03-25T20:21:39.316Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/71dfd96bcc1c775420cb8befe7a9d35f2e5b1309798f009dca17b7708c1e/tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36", size = 108755, upload-time = "2026-03-25T20:21:40.248Z" }, + { url = "https://files.pythonhosted.org/packages/83/7a/d34f422a021d62420b78f5c538e5b102f62bea616d1d75a13f0a88acb04a/tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd", size = 95265, upload-time = "2026-03-25T20:21:41.219Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fb/9a5c8d27dbab540869f7c1f8eb0abb3244189ce780ba9cd73f3770662072/tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf", size = 155726, upload-time = "2026-03-25T20:21:42.23Z" }, + { url = "https://files.pythonhosted.org/packages/62/05/d2f816630cc771ad836af54f5001f47a6f611d2d39535364f148b6a92d6b/tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac", size = 149859, upload-time = "2026-03-25T20:21:43.386Z" }, + { url = "https://files.pythonhosted.org/packages/ce/48/66341bdb858ad9bd0ceab5a86f90eddab127cf8b046418009f2125630ecb/tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662", size = 244713, upload-time = "2026-03-25T20:21:44.474Z" }, + { url = "https://files.pythonhosted.org/packages/df/6d/c5fad00d82b3c7a3ab6189bd4b10e60466f22cfe8a08a9394185c8a8111c/tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853", size = 252084, upload-time = "2026-03-25T20:21:45.62Z" }, + { url = "https://files.pythonhosted.org/packages/00/71/3a69e86f3eafe8c7a59d008d245888051005bd657760e96d5fbfb0b740c2/tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15", size = 247973, upload-time = "2026-03-25T20:21:46.937Z" }, + { url = "https://files.pythonhosted.org/packages/67/50/361e986652847fec4bd5e4a0208752fbe64689c603c7ae5ea7cb16b1c0ca/tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba", size = 256223, upload-time = "2026-03-25T20:21:48.467Z" }, + { url = "https://files.pythonhosted.org/packages/8c/9a/b4173689a9203472e5467217e0154b00e260621caa227b6fa01feab16998/tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6", size = 98973, upload-time = "2026-03-25T20:21:49.526Z" }, + { url = "https://files.pythonhosted.org/packages/14/58/640ac93bf230cd27d002462c9af0d837779f8773bc03dee06b5835208214/tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7", size = 109082, upload-time = "2026-03-25T20:21:50.506Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2f/702d5e05b227401c1068f0d386d79a589bb12bf64c3d2c72ce0631e3bc49/tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232", size = 96490, upload-time = "2026-03-25T20:21:51.474Z" }, + { url = "https://files.pythonhosted.org/packages/45/4b/b877b05c8ba62927d9865dd980e34a755de541eb65fffba52b4cc495d4d2/tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4", size = 164263, upload-time = "2026-03-25T20:21:52.543Z" }, + { url = "https://files.pythonhosted.org/packages/24/79/6ab420d37a270b89f7195dec5448f79400d9e9c1826df982f3f8e97b24fd/tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c", size = 160736, upload-time = "2026-03-25T20:21:53.674Z" }, + { url = "https://files.pythonhosted.org/packages/02/e0/3630057d8eb170310785723ed5adcdfb7d50cb7e6455f85ba8a3deed642b/tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d", size = 270717, upload-time = "2026-03-25T20:21:55.129Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/1613716072e544d1a7891f548d8f9ec6ce2faf42ca65acae01d76ea06bb0/tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41", size = 278461, upload-time = "2026-03-25T20:21:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/05/38/30f541baf6a3f6df77b3df16b01ba319221389e2da59427e221ef417ac0c/tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c", size = 274855, upload-time = "2026-03-25T20:21:57.653Z" }, + { url = "https://files.pythonhosted.org/packages/77/a3/ec9dd4fd2c38e98de34223b995a3b34813e6bdadf86c75314c928350ed14/tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f", size = 283144, upload-time = "2026-03-25T20:21:59.089Z" }, + { url = "https://files.pythonhosted.org/packages/ef/be/605a6261cac79fba2ec0c9827e986e00323a1945700969b8ee0b30d85453/tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8", size = 108683, upload-time = "2026-03-25T20:22:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/12/64/da524626d3b9cc40c168a13da8335fe1c51be12c0a63685cc6db7308daae/tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26", size = 121196, upload-time = "2026-03-25T20:22:01.169Z" }, + { url = "https://files.pythonhosted.org/packages/5a/cd/e80b62269fc78fc36c9af5a6b89c835baa8af28ff5ad28c7028d60860320/tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396", size = 100393, upload-time = "2026-03-25T20:22:02.137Z" }, + { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" }, +] + +[[package]] +name = "torch" +version = "2.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "fsspec" }, + { name = "jinja2" }, + { name = "networkx" }, + { name = "nvidia-cublas-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cuda-cupti-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cuda-nvrtc-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cuda-runtime-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cudnn-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cufft-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cufile-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-curand-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cusolver-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cusparse-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-cusparselt-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-nccl-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-nvjitlink-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "nvidia-nvtx-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "setuptools", marker = "python_full_version >= '3.12'" }, + { name = "sympy" }, + { name = "triton", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" }, + { name = "typing-extensions" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/27/2e06cb52adf89fe6e020963529d17ed51532fc73c1e6d1b18420ef03338c/torch-2.7.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:a103b5d782af5bd119b81dbcc7ffc6fa09904c423ff8db397a1e6ea8fd71508f", size = 99089441, upload-time = "2025-06-04T17:38:48.268Z" }, + { url = "https://files.pythonhosted.org/packages/0a/7c/0a5b3aee977596459ec45be2220370fde8e017f651fecc40522fd478cb1e/torch-2.7.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:fe955951bdf32d182ee8ead6c3186ad54781492bf03d547d31771a01b3d6fb7d", size = 821154516, upload-time = "2025-06-04T17:36:28.556Z" }, + { url = "https://files.pythonhosted.org/packages/f9/91/3d709cfc5e15995fb3fe7a6b564ce42280d3a55676dad672205e94f34ac9/torch-2.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:885453d6fba67d9991132143bf7fa06b79b24352f4506fd4d10b309f53454162", size = 216093147, upload-time = "2025-06-04T17:39:38.132Z" }, + { url = "https://files.pythonhosted.org/packages/92/f6/5da3918414e07da9866ecb9330fe6ffdebe15cb9a4c5ada7d4b6e0a6654d/torch-2.7.1-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:d72acfdb86cee2a32c0ce0101606f3758f0d8bb5f8f31e7920dc2809e963aa7c", size = 68630914, upload-time = "2025-06-04T17:39:31.162Z" }, + { url = "https://files.pythonhosted.org/packages/11/56/2eae3494e3d375533034a8e8cf0ba163363e996d85f0629441fa9d9843fe/torch-2.7.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:236f501f2e383f1cb861337bdf057712182f910f10aeaf509065d54d339e49b2", size = 99093039, upload-time = "2025-06-04T17:39:06.963Z" }, + { url = "https://files.pythonhosted.org/packages/e5/94/34b80bd172d0072c9979708ccd279c2da2f55c3ef318eceec276ab9544a4/torch-2.7.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:06eea61f859436622e78dd0cdd51dbc8f8c6d76917a9cf0555a333f9eac31ec1", size = 821174704, upload-time = "2025-06-04T17:37:03.799Z" }, + { url = "https://files.pythonhosted.org/packages/50/9e/acf04ff375b0b49a45511c55d188bcea5c942da2aaf293096676110086d1/torch-2.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:8273145a2e0a3c6f9fd2ac36762d6ee89c26d430e612b95a99885df083b04e52", size = 216095937, upload-time = "2025-06-04T17:39:24.83Z" }, + { url = "https://files.pythonhosted.org/packages/5b/2b/d36d57c66ff031f93b4fa432e86802f84991477e522adcdffd314454326b/torch-2.7.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:aea4fc1bf433d12843eb2c6b2204861f43d8364597697074c8d38ae2507f8730", size = 68640034, upload-time = "2025-06-04T17:39:17.989Z" }, + { url = "https://files.pythonhosted.org/packages/87/93/fb505a5022a2e908d81fe9a5e0aa84c86c0d5f408173be71c6018836f34e/torch-2.7.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:27ea1e518df4c9de73af7e8a720770f3628e7f667280bce2be7a16292697e3fa", size = 98948276, upload-time = "2025-06-04T17:39:12.852Z" }, + { url = "https://files.pythonhosted.org/packages/56/7e/67c3fe2b8c33f40af06326a3d6ae7776b3e3a01daa8f71d125d78594d874/torch-2.7.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c33360cfc2edd976c2633b3b66c769bdcbbf0e0b6550606d188431c81e7dd1fc", size = 821025792, upload-time = "2025-06-04T17:34:58.747Z" }, + { url = "https://files.pythonhosted.org/packages/a1/37/a37495502bc7a23bf34f89584fa5a78e25bae7b8da513bc1b8f97afb7009/torch-2.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:d8bf6e1856ddd1807e79dc57e54d3335f2b62e6f316ed13ed3ecfe1fc1df3d8b", size = 216050349, upload-time = "2025-06-04T17:38:59.709Z" }, + { url = "https://files.pythonhosted.org/packages/3a/60/04b77281c730bb13460628e518c52721257814ac6c298acd25757f6a175c/torch-2.7.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:787687087412c4bd68d315e39bc1223f08aae1d16a9e9771d95eabbb04ae98fb", size = 68645146, upload-time = "2025-06-04T17:38:52.97Z" }, + { url = "https://files.pythonhosted.org/packages/66/81/e48c9edb655ee8eb8c2a6026abdb6f8d2146abd1f150979ede807bb75dcb/torch-2.7.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:03563603d931e70722dce0e11999d53aa80a375a3d78e6b39b9f6805ea0a8d28", size = 98946649, upload-time = "2025-06-04T17:38:43.031Z" }, + { url = "https://files.pythonhosted.org/packages/3a/24/efe2f520d75274fc06b695c616415a1e8a1021d87a13c68ff9dce733d088/torch-2.7.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:d632f5417b6980f61404a125b999ca6ebd0b8b4bbdbb5fbbba44374ab619a412", size = 821033192, upload-time = "2025-06-04T17:38:09.146Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d9/9c24d230333ff4e9b6807274f6f8d52a864210b52ec794c5def7925f4495/torch-2.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:23660443e13995ee93e3d844786701ea4ca69f337027b05182f5ba053ce43b38", size = 216055668, upload-time = "2025-06-04T17:38:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/95/bf/e086ee36ddcef9299f6e708d3b6c8487c1651787bb9ee2939eb2a7f74911/torch-2.7.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:0da4f4dba9f65d0d203794e619fe7ca3247a55ffdcbd17ae8fb83c8b2dc9b585", size = 68925988, upload-time = "2025-06-04T17:38:29.273Z" }, + { url = "https://files.pythonhosted.org/packages/69/6a/67090dcfe1cf9048448b31555af6efb149f7afa0a310a366adbdada32105/torch-2.7.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:e08d7e6f21a617fe38eeb46dd2213ded43f27c072e9165dc27300c9ef9570934", size = 99028857, upload-time = "2025-06-04T17:37:50.956Z" }, + { url = "https://files.pythonhosted.org/packages/90/1c/48b988870823d1cc381f15ec4e70ed3d65e043f43f919329b0045ae83529/torch-2.7.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:30207f672328a42df4f2174b8f426f354b2baa0b7cca3a0adb3d6ab5daf00dc8", size = 821098066, upload-time = "2025-06-04T17:37:33.939Z" }, + { url = "https://files.pythonhosted.org/packages/7b/eb/10050d61c9d5140c5dc04a89ed3257ef1a6b93e49dd91b95363d757071e0/torch-2.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:79042feca1c634aaf6603fe6feea8c6b30dfa140a6bbc0b973e2260c7e79a22e", size = 216336310, upload-time = "2025-06-04T17:36:09.862Z" }, + { url = "https://files.pythonhosted.org/packages/b1/29/beb45cdf5c4fc3ebe282bf5eafc8dfd925ead7299b3c97491900fe5ed844/torch-2.7.1-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:988b0cbc4333618a1056d2ebad9eb10089637b659eb645434d0809d8d937b946", size = 68645708, upload-time = "2025-06-04T17:34:39.852Z" }, +] + +[[package]] +name = "tqdm" +version = "4.67.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e8/4f/0153c21dc5779a49a0598c445b1978126b1344bab9ee71e53e44877e14e0/tqdm-4.67.0.tar.gz", hash = "sha256:fe5a6f95e6fe0b9755e9469b77b9c3cf850048224ecaa8293d7d2d31f97d869a", size = 169739, upload-time = "2024-11-06T16:35:37.677Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/78/57043611a16c655c8350b4c01b8d6abfb38cc2acb475238b62c2146186d7/tqdm-4.67.0-py3-none-any.whl", hash = "sha256:0cd8af9d56911acab92182e88d763100d4788bdf421d251616040cc4d44863be", size = 78590, upload-time = "2024-11-06T16:35:35.023Z" }, +] + +[[package]] +name = "transformers" +version = "4.53.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "huggingface-hub" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "regex" }, + { name = "requests" }, + { name = "safetensors" }, + { name = "tokenizers" }, + { name = "tqdm" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/2c/68a0024c311db41bb92d4ec17d22e90b7406a4d28aa18d87662f2bbebcd9/transformers-4.53.1.tar.gz", hash = "sha256:da5a9f66ad480bc2a7f75bc32eaf735fd20ac56af4325ca4ce994021ceb37710", size = 9192189, upload-time = "2025-07-04T08:28:40.571Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/10/8cef2288810a3210659eb3a20711e8387cc35a881a7762ae387806e2d651/transformers-4.53.1-py3-none-any.whl", hash = "sha256:c84f3c3e41c71fdf2c60c8a893e1cd31191b0cb463385f4c276302d2052d837b", size = 10825681, upload-time = "2025-07-04T08:28:37.318Z" }, +] + +[[package]] +name = "triton" +version = "3.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "setuptools" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/a9/549e51e9b1b2c9b854fd761a1d23df0ba2fbc60bd0c13b489ffa518cfcb7/triton-3.3.1-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b74db445b1c562844d3cfad6e9679c72e93fdfb1a90a24052b03bb5c49d1242e", size = 155600257, upload-time = "2025-05-29T23:39:36.085Z" }, + { url = "https://files.pythonhosted.org/packages/21/2f/3e56ea7b58f80ff68899b1dbe810ff257c9d177d288c6b0f55bf2fe4eb50/triton-3.3.1-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b31e3aa26f8cb3cc5bf4e187bf737cbacf17311e1112b781d4a059353dfd731b", size = 155689937, upload-time = "2025-05-29T23:39:44.182Z" }, + { url = "https://files.pythonhosted.org/packages/24/5f/950fb373bf9c01ad4eb5a8cd5eaf32cdf9e238c02f9293557a2129b9c4ac/triton-3.3.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9999e83aba21e1a78c1f36f21bce621b77bcaa530277a50484a7cb4a822f6e43", size = 155669138, upload-time = "2025-05-29T23:39:51.771Z" }, + { url = "https://files.pythonhosted.org/packages/74/1f/dfb531f90a2d367d914adfee771babbd3f1a5b26c3f5fbc458dee21daa78/triton-3.3.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b89d846b5a4198317fec27a5d3a609ea96b6d557ff44b56c23176546023c4240", size = 155673035, upload-time = "2025-05-29T23:40:02.468Z" }, + { url = "https://files.pythonhosted.org/packages/28/71/bd20ffcb7a64c753dc2463489a61bf69d531f308e390ad06390268c4ea04/triton-3.3.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3198adb9d78b77818a5388bff89fa72ff36f9da0bc689db2f0a651a67ce6a42", size = 155735832, upload-time = "2025-05-29T23:40:10.522Z" }, +] + +[[package]] +name = "typer" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8f/28/7c85c8032b91dbe79725b6f17d2fffc595dff06a35c7a30a37bef73a1ab4/typer-0.20.0.tar.gz", hash = "sha256:1aaf6494031793e4876fb0bacfa6a912b551cf43c1e63c800df8b1a866720c37", size = 106492, upload-time = "2025-10-20T17:03:49.445Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/64/7713ffe4b5983314e9d436a90d5bd4f63b6054e2aca783a3cfc44cb95bbf/typer-0.20.0-py3-none-any.whl", hash = "sha256:5b463df6793ec1dca6213a3cf4c0f03bc6e322ac5e16e13ddd622a889489784a", size = 47028, upload-time = "2025-10-20T17:03:47.617Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "tzdata" +version = "2025.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380, upload-time = "2025-03-23T13:54:43.652Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839, upload-time = "2025-03-23T13:54:41.845Z" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + +[[package]] +name = "wasabi" +version = "1.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/f9/054e6e2f1071e963b5e746b48d1e3727470b2a490834d18ad92364929db3/wasabi-1.1.3.tar.gz", hash = "sha256:4bb3008f003809db0c3e28b4daf20906ea871a2bb43f9914197d540f4f2e0878", size = 30391, upload-time = "2024-05-31T16:56:18.99Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/7c/34330a89da55610daa5f245ddce5aab81244321101614751e7537f125133/wasabi-1.1.3-py3-none-any.whl", hash = "sha256:f76e16e8f7e79f8c4c8be49b4024ac725713ab10cd7f19350ad18a8e3f71728c", size = 27880, upload-time = "2024-05-31T16:56:16.699Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.2.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, +] + +[[package]] +name = "weasel" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cloudpathlib" }, + { name = "confection" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "requests" }, + { name = "smart-open" }, + { name = "srsly" }, + { name = "typer" }, + { name = "wasabi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a7/1a/9c522dd61b52939c217925d3e55c95f9348b73a66a956f52608e1e59a2c0/weasel-0.4.1.tar.gz", hash = "sha256:aabc210f072e13f6744e5c3a28037f93702433405cd35673f7c6279147085aa9", size = 38417, upload-time = "2024-05-15T08:52:54.765Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/87/abd57374044e1f627f0a905ac33c1a7daab35a3a815abfea4e1bafd3fdb1/weasel-0.4.1-py3-none-any.whl", hash = "sha256:24140a090ea1ac512a2b2f479cc64192fd1d527a7f3627671268d08ed5ac418c", size = 50270, upload-time = "2024-05-15T08:52:52.977Z" }, +] + +[[package]] +name = "wordfreq" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ftfy" }, + { name = "langcodes" }, + { name = "locate" }, + { name = "msgpack" }, + { name = "regex" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/cd/9581ff0ea2c581012d0caae4bba024f3ff6b46e030a55ddec1ce545e2caf/wordfreq-3.1.1.tar.gz", hash = "sha256:7943098975f25c2a70e1151ee5a62083b14a5f86f6cc5703cc9526f716ceb408", size = 56846562, upload-time = "2023-11-21T23:09:12.106Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/24/61/62835c475d69872d30689f284497853fe33fe1d6dd18f57346d13305861d/wordfreq-3.1.1-py3-none-any.whl", hash = "sha256:4b1c6ecffc6198be3396d5cf871c4423ca71c907c231348d352dd54d62b97473", size = 56834549, upload-time = "2023-11-21T23:09:07.183Z" }, +] + +[[package]] +name = "wrapt" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/19/5e5bcd855d808892fe02d49219f97a50f64cd6d8313d75df3494ee97b1a3/wrapt-2.0.0.tar.gz", hash = "sha256:35a542cc7a962331d0279735c30995b024e852cf40481e384fd63caaa391cbb9", size = 81722, upload-time = "2025-10-19T23:47:54.07Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/db/ac9546e89b645e525686727f8749847485e3b45ffc4507b61c4669358638/wrapt-2.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a7cebcee61f21b1e46aa32db8d9d93826d0fbf1ad85defc2ccfb93b4adef1435", size = 77431, upload-time = "2025-10-19T23:45:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/74/bc/3b57c8012bbd0d02eec5ae838681c1a819df6c5e765ebc897f52623b5eb1/wrapt-2.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:827e6e3a3a560f6ec1f5ee92d4319c21a0549384f896ec692f3201eda31ebd11", size = 60644, upload-time = "2025-10-19T23:45:27.511Z" }, + { url = "https://files.pythonhosted.org/packages/b8/6e/b5e7d47713e3d46c30ec6ae83fafd369bc34de8148668c6e3168d9301863/wrapt-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a91075a5383a7cbfe46aed1845ef7c3f027e8e20e7d9a8a75e36ebc9b0dd15e", size = 61526, upload-time = "2025-10-19T23:45:28.789Z" }, + { url = "https://files.pythonhosted.org/packages/28/8d/d5df2af58ae479785473607a3b25726c295640cdcaee830847cee339eff9/wrapt-2.0.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b6a18c813196e18146b8d041e20875bdb0cb09b94ac1d1e1146e0fa87b2deb0d", size = 113638, upload-time = "2025-10-19T23:45:31.977Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b7/9501c45ab93b4d6ba396ef02fcfb55867866bc8579fff045bb54cae58423/wrapt-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec5028d26011a53c76bd91bb6198b30b438c6e0f7adb45f2ad84fe2655b6a104", size = 115651, upload-time = "2025-10-19T23:45:33.257Z" }, + { url = "https://files.pythonhosted.org/packages/5e/3a/bfebe2ba51cf98ae80c5dbb6fa5892ae75d1acf1a4c404eda88e28f5ab06/wrapt-2.0.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bed9b04900204721a24bcefc652ca267b01c1e8ad8bc8c0cff81558a45a3aadc", size = 112060, upload-time = "2025-10-19T23:45:30.298Z" }, + { url = "https://files.pythonhosted.org/packages/00/e7/cd50a32bed022d98f61a90e57faf782aa063f7930f57eb67eb105d3189be/wrapt-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:03442f2b45fa3f2b98a94a1917f52fb34670de8f96c0a009c02dbd512d855a3d", size = 114829, upload-time = "2025-10-19T23:45:34.23Z" }, + { url = "https://files.pythonhosted.org/packages/9d/2c/c709578271df0c70a27ab8f797c44c258650f24a32b452f03d7afedc070d/wrapt-2.0.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:17d0b5c42495ba142a1cee52b76414f9210591c84aae94dffda70240753bfb3c", size = 111249, upload-time = "2025-10-19T23:45:35.554Z" }, + { url = "https://files.pythonhosted.org/packages/60/ef/cb58f6eea41f129600bda68d1ae4c80b14d4e0663eec1d5220cbffe50be5/wrapt-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ee44215e7d13e112a8fc74e12ed1a1f41cab2bc07b11cc703f2398cd114b261c", size = 113312, upload-time = "2025-10-19T23:45:36.66Z" }, + { url = "https://files.pythonhosted.org/packages/59/55/97e6c4e1c175fb27f8dec717a3e36493ff0c4e50173a95f439496556910f/wrapt-2.0.0-cp310-cp310-win32.whl", hash = "sha256:fe6eafac3bc3c957ab6597a0c0654a0a308868458d00d218743e5b5fae51951c", size = 57961, upload-time = "2025-10-19T23:45:40.958Z" }, + { url = "https://files.pythonhosted.org/packages/3b/0a/898b1d81ae1f3dd9a79fd2e0330a7c8dd793982f815a318548777cb21ee5/wrapt-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:9e070c3491397fba0445b8977900271eca9656570cca7c900d9b9352186703a0", size = 60311, upload-time = "2025-10-19T23:45:38.033Z" }, + { url = "https://files.pythonhosted.org/packages/44/f1/e7e92f9535f5624ee22879f09456df9d1f1ae9bb338eef711077b48e456a/wrapt-2.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:806e2e73186eb5e3546f39fb5d0405040e0088db0fc8b2f667fd1863de2b3c99", size = 58822, upload-time = "2025-10-19T23:45:39.785Z" }, + { url = "https://files.pythonhosted.org/packages/12/8f/8e4c8b6da60b4205191d588cbac448fb9ff4f5ed89f4e555dc4813ab30cf/wrapt-2.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b7e221abb6c5387819db9323dac3c875b459695057449634f1111955d753c621", size = 77433, upload-time = "2025-10-19T23:45:42.543Z" }, + { url = "https://files.pythonhosted.org/packages/22/9a/01a29ccb029aa8e78241f8b53cb89ae8826c240129abbbb6ebba3416eff9/wrapt-2.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1147a84c8fc852426580af8b6e33138461ddbc65aa459a25ea539374d32069fa", size = 60641, upload-time = "2025-10-19T23:45:43.866Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ec/e058997971428b7665b5c3665a55b18bb251ea7e08d002925e3ca017c020/wrapt-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d6691d4a711504a0bc10de789842ad6ac627bed22937b10f37a1211a8ab7bb3", size = 61526, upload-time = "2025-10-19T23:45:44.839Z" }, + { url = "https://files.pythonhosted.org/packages/70/c3/c82263503f554715aa1847e85dc75a69631a54e9d7ab0f1a55e34a22d44a/wrapt-2.0.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f460e1eb8e75a17c3918c8e35ba57625721eef2439ef0bcf05304ac278a65e1d", size = 114069, upload-time = "2025-10-19T23:45:47.223Z" }, + { url = "https://files.pythonhosted.org/packages/dc/97/d95e88a3a1bc2890a1aa47880c2762cf0eb6d231b5a64048e351cec6f071/wrapt-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:12c37784b77bf043bf65cc96c7195a5db474b8e54173208af076bdbb61df7b3e", size = 116109, upload-time = "2025-10-19T23:45:48.252Z" }, + { url = "https://files.pythonhosted.org/packages/dc/36/cba0bf954f2303897b80fa5342499b43f8c5201110dddf0d578d6841b149/wrapt-2.0.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75e5c049eb583835f7a0e0e311d9dde9bfbaac723a6dd89d052540f9b2809977", size = 112500, upload-time = "2025-10-19T23:45:45.838Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2b/8cb88e63bec989f641d208acb3fd198bfdbbb4ef7dfb71f0cac3c90b07a9/wrapt-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e50bcbd5b65dac21b82319fcf18486e6ac439947e9305034b00704eb7405f553", size = 115356, upload-time = "2025-10-19T23:45:49.249Z" }, + { url = "https://files.pythonhosted.org/packages/bb/60/a6d5fb94648cd430648705bef9f4241bd22ead123ead552b6d2873ad5240/wrapt-2.0.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:06b78cb6b9320f57737a52fede882640d93cface98332d1a3df0c5696ec9ae9f", size = 111754, upload-time = "2025-10-19T23:45:51.21Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/1963854edf0592ae806307899dc7bf891e76cec19e598f55845c94603a65/wrapt-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c8349ebfc3cd98bc9105e0112dd8c8ac1f3c7cb5601f9d02248cae83a63f748", size = 113789, upload-time = "2025-10-19T23:45:52.473Z" }, + { url = "https://files.pythonhosted.org/packages/62/ec/4b1d76cb6d96ac511aaaa92efc57f528e57f06082a595b8b2663fcdb0f20/wrapt-2.0.0-cp311-cp311-win32.whl", hash = "sha256:028f19ec29e204fe725139d4a8b09f77ecfb64f8f02b7ab5ee822c85e330b68b", size = 57954, upload-time = "2025-10-19T23:45:57.03Z" }, + { url = "https://files.pythonhosted.org/packages/d4/cf/df8ff9bd64d4a75f9a9f6c1c93480a51904d0c9bd71c11994301c47d8a33/wrapt-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:c6961f05e58d919153ba311b397b7b904b907132b7b8344dde47865d4bb5ec89", size = 60308, upload-time = "2025-10-19T23:45:54.314Z" }, + { url = "https://files.pythonhosted.org/packages/69/d8/61e245fe387d58d84b3f913d5da9d909c4f239b887db692a05105aaf2a1b/wrapt-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:be7e316c2accd5a31dbcc230de19e2a846a325f8967fdea72704d00e38e6af06", size = 58822, upload-time = "2025-10-19T23:45:55.772Z" }, + { url = "https://files.pythonhosted.org/packages/3c/28/7f266b5bf50c3ad0c99c524d99faa0f7d6eecb045d950e7d2c9e1f0e1338/wrapt-2.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73c6f734aecb1a030d9a265c13a425897e1ea821b73249bb14471445467ca71c", size = 78078, upload-time = "2025-10-19T23:45:58.855Z" }, + { url = "https://files.pythonhosted.org/packages/06/0c/bbdcad7eb535fae9d6b0fcfa3995c364797cd8e2b423bba5559ab2d88dcf/wrapt-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b4a7f8023b8ce8a36370154733c747f8d65c8697cb977d8b6efeb89291fff23e", size = 61158, upload-time = "2025-10-19T23:46:00.096Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8a/bba3e7a4ebf4d1624103ee59d97b78a1fbb08fb5753ff5d1b69f5ef5e863/wrapt-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a1cb62f686c50e9dab5983c68f6c8e9cbf14a6007935e683662898a7d892fa69", size = 61646, upload-time = "2025-10-19T23:46:01.279Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0c/0f565294897a72493dbafe7b46229b5f09f3776795a894d6b737e98387de/wrapt-2.0.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:43dc0550ae15e33e6bb45a82a5e1b5495be2587fbaa996244b509921810ee49f", size = 121442, upload-time = "2025-10-19T23:46:04.287Z" }, + { url = "https://files.pythonhosted.org/packages/da/80/7f03501a8a078ad79b19b1a888f9192a9494e62ddf8985267902766a4f30/wrapt-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39c5b45b056d630545e40674d1f5e1b51864b3546f25ab6a4a331943de96262e", size = 123018, upload-time = "2025-10-19T23:46:06.052Z" }, + { url = "https://files.pythonhosted.org/packages/37/6b/ad0e1ff98359f13b4b0c2c52848e792841146fe79ac5f56899b9a028fc0d/wrapt-2.0.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:804e88f824b76240a1b670330637ccfd2d18b9efa3bb4f02eb20b2f64880b324", size = 117369, upload-time = "2025-10-19T23:46:02.53Z" }, + { url = "https://files.pythonhosted.org/packages/ac/6c/a90437bba8cb1ce2ed639af979515e09784678c2a7f4ffc79f2cf7de809e/wrapt-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c2c476aa3fc2b9899c3f7b20963fac4f952e7edb74a31fc92f7745389a2e3618", size = 121453, upload-time = "2025-10-19T23:46:07.747Z" }, + { url = "https://files.pythonhosted.org/packages/2c/a9/b3982f9bd15bd45857a23c48b7c36e47d05db4a4dcc5061c31f169238845/wrapt-2.0.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8d851e526891216f89fcb7a1820dad9bd503ba3468fb9635ee28e93c781aa98e", size = 116250, upload-time = "2025-10-19T23:46:09.385Z" }, + { url = "https://files.pythonhosted.org/packages/73/e2/b7a8b1afac9f791d8f5eac0d9726559f1d7ec4a2b5a6b4e67ac145b007a5/wrapt-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b95733c2360c4a8656ee93c7af78e84c0bd617da04a236d7a456c8faa34e7a2d", size = 120575, upload-time = "2025-10-19T23:46:11.882Z" }, + { url = "https://files.pythonhosted.org/packages/a2/0f/37920eeea96094f450ae35505d39f1135df951a2cdee0d4e01d4f843396a/wrapt-2.0.0-cp312-cp312-win32.whl", hash = "sha256:ea56817176834edf143df1109ae8fdaa087be82fdad3492648de0baa8ae82bf2", size = 58175, upload-time = "2025-10-19T23:46:15.678Z" }, + { url = "https://files.pythonhosted.org/packages/f0/db/b395f3b0c7f2c60d9219afacc54ceb699801ccf2d3d969ba556dc6d3af20/wrapt-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:3c7d3bee7be7a2665286103f4d1f15405c8074e6e1f89dac5774f9357c9a3809", size = 60415, upload-time = "2025-10-19T23:46:12.913Z" }, + { url = "https://files.pythonhosted.org/packages/86/22/33d660214548af47fc59d9eec8c0e0693bcedc5b3a0b52e8cbdd61f3b646/wrapt-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:680f707e1d26acbc60926659799b15659f077df5897a6791c7c598a5d4a211c4", size = 58911, upload-time = "2025-10-19T23:46:13.889Z" }, + { url = "https://files.pythonhosted.org/packages/18/0a/dd88abfe756b1aa79f0777e5ee4ce9e4b5dc4999bd805e9b04b52efc7b18/wrapt-2.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e2ea096db28d5eb64d381af0e93464621ace38a7003a364b6b5ffb7dd713aabe", size = 78083, upload-time = "2025-10-19T23:46:16.937Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b9/8afebc1655a863bb2178b23c2d699b8743f3a7dab466904adc6155f3c858/wrapt-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c92b5a82d28491e3f14f037e1aae99a27a5e6e0bb161e65f52c0445a3fa7c940", size = 61156, upload-time = "2025-10-19T23:46:17.927Z" }, + { url = "https://files.pythonhosted.org/packages/bb/8b/f710a6528ccc52e21943f42c8cf64814cde90f9adbd3bcd58c7c274b4f75/wrapt-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:81d234718aabe632d179fac52c7f69f0f99fbaac4d4bcd670e62462bbcbfcad7", size = 61641, upload-time = "2025-10-19T23:46:19.229Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5f/e4eabd0cc6684c5b208c2abc5c3459449c4d15be1694a9bbcf51e0e135fd/wrapt-2.0.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:db2eea83c43f84e4e41dbbb4c1de371a53166e55f900a6b130c3ef51c6345c1a", size = 121454, upload-time = "2025-10-19T23:46:21.808Z" }, + { url = "https://files.pythonhosted.org/packages/6f/c4/ec31ee17cc7866960d323609ba7402be786d211a6d713a59f776c4270bb3/wrapt-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65f50e356c425c061e1e17fe687ff30e294fed9bf3441dc1f13ef73859c2a817", size = 123063, upload-time = "2025-10-19T23:46:23.545Z" }, + { url = "https://files.pythonhosted.org/packages/b0/2b/a4b10c3c0022e40aeae9bec009bafb049f440493f0575ebb27ecf61c32f8/wrapt-2.0.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:887f2a667e3cbfb19e204032d42ad7dedaa43972e4861dc7a3d51ae951d9b578", size = 117401, upload-time = "2025-10-19T23:46:20.433Z" }, + { url = "https://files.pythonhosted.org/packages/2a/4a/ade23a76967e1f148e461076a4d0e24a7950a5f18b394c9107fe60224ae2/wrapt-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9054829da4be461e3ad3192e4b6bbf1fc18af64c9975ce613aec191924e004dc", size = 121485, upload-time = "2025-10-19T23:46:24.85Z" }, + { url = "https://files.pythonhosted.org/packages/cb/ba/33b5f3e2edede4e1cfd259f0d9c203cf370f259bb9b215dd58fc6cbb94e9/wrapt-2.0.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b952ffd77133a5a2798ee3feb18e51b0a299d2f440961e5bb7737dbb02e57289", size = 116276, upload-time = "2025-10-19T23:46:27.006Z" }, + { url = "https://files.pythonhosted.org/packages/eb/bf/b7f95bb4529a35ca11eb95d48f9d1a563b495471f7cf404c644566fb4293/wrapt-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e25fde03c480061b8234d8ee4863eb5f40a9be4fb258ce105b364de38fc6bcf9", size = 120578, upload-time = "2025-10-19T23:46:28.679Z" }, + { url = "https://files.pythonhosted.org/packages/f8/71/984849df6f052592474a44aafd6b847e1cffad39b0debc5390a04aa46331/wrapt-2.0.0-cp313-cp313-win32.whl", hash = "sha256:49e982b7860d325094978292a49e0418833fc7fc42c0dc7cd0b7524d7d06ee74", size = 58178, upload-time = "2025-10-19T23:46:32.372Z" }, + { url = "https://files.pythonhosted.org/packages/f9/3b/4e1fc0f2e1355fbc55ab248311bf4c958dbbd96bd9183b9e96882cc16213/wrapt-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:6e5c86389d9964050ce50babe247d172a5e3911d59a64023b90db2b4fa00ae7c", size = 60423, upload-time = "2025-10-19T23:46:30.041Z" }, + { url = "https://files.pythonhosted.org/packages/20/0a/9384e0551f56fe361f41bb8f209a13bb9ef689c3a18264225b249849b12c/wrapt-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:b96fdaa4611e05c7231937930567d3c16782be9dbcf03eb9f60d83e57dd2f129", size = 58918, upload-time = "2025-10-19T23:46:31.056Z" }, + { url = "https://files.pythonhosted.org/packages/68/70/37b90d3ee5bf0d0dc4859306383da08b685c9a51abff6fd6b0a7c052e117/wrapt-2.0.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f2c7b7fead096dbf1dcc455b7f59facb05de3f5bfb04f60a69f98cdfe6049e5f", size = 81980, upload-time = "2025-10-19T23:46:33.368Z" }, + { url = "https://files.pythonhosted.org/packages/95/23/0ce69cc90806b90b3ee4cfd9ad8d2ee9becc3a1aab7df3c3bfc7d0904cb6/wrapt-2.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:04c7c8393f25b11c0faa5d907dd9eb462e87e4e7ba55e308a046d7ed37f4bbe2", size = 62900, upload-time = "2025-10-19T23:46:34.415Z" }, + { url = "https://files.pythonhosted.org/packages/54/76/03ec08170c02f38f3be3646977920976b968e0b704a0693a98f95d02f4d2/wrapt-2.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a93e0f8b376c0735b2f4daf58018b4823614d2b896cb72b6641c4d3dbdca1d75", size = 63636, upload-time = "2025-10-19T23:46:35.643Z" }, + { url = "https://files.pythonhosted.org/packages/75/c1/04ce0511e504cdcd84cdb6980bc7d4efa38ac358e8103d6dd0cd278bfc6d/wrapt-2.0.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b42d13603da4416c43c430dbc6313c8d7ff745c40942f146ed4f6dd02c7d2547", size = 152650, upload-time = "2025-10-19T23:46:38.717Z" }, + { url = "https://files.pythonhosted.org/packages/17/06/cd2e32b5f744701189c954f9ab5eee449c86695b13f414bb8ea7a83f6d48/wrapt-2.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8bbd2472abf8c33480ad2314b1f8fac45d592aba6cc093e8839a7b2045660e6", size = 158811, upload-time = "2025-10-19T23:46:40.875Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a2/a6d920695cca62563c1b969064e5cd2051344a6e330c184b6f80383d87e4/wrapt-2.0.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e64a3a1fd9a308ab9b815a2ad7a65b679730629dbf85f8fc3f7f970d634ee5df", size = 146033, upload-time = "2025-10-19T23:46:37.351Z" }, + { url = "https://files.pythonhosted.org/packages/c6/90/7fd2abe4ec646bc43cb6b0d05086be6fcf15e64f06f51fc4198804396d68/wrapt-2.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d61214525eaf88e0d0edf3d1ad5b5889863c6f88e588c6cdc6aa4ee5d1f10a4a", size = 155673, upload-time = "2025-10-19T23:46:42.582Z" }, + { url = "https://files.pythonhosted.org/packages/5f/8d/6cce7f8c41633e677ac8aa34e84b53a22a645ec2a680deb991785ca2798d/wrapt-2.0.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:04f7a5f92c5f7324a1735043cc467b1295a1c5b4e0c1395472b7c44706e3dc61", size = 144364, upload-time = "2025-10-19T23:46:44.381Z" }, + { url = "https://files.pythonhosted.org/packages/72/42/9570349e03afa9d83daf7f33ffb17e8cdc62d7e84c0d09005d0f51912efa/wrapt-2.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2356f76cb99b3de5b4e5b8210367fbbb81c7309fe39b622f5d199dd88eb7f765", size = 150275, upload-time = "2025-10-19T23:46:45.662Z" }, + { url = "https://files.pythonhosted.org/packages/f2/d8/448728e6fe030e5c4f1022c82cd3af1de1c672fa53d2d5b36b32a55ce7bf/wrapt-2.0.0-cp313-cp313t-win32.whl", hash = "sha256:0a921b657a224e40e4bc161b5d33934583b34f0c9c5bdda4e6ac66f9d2fcb849", size = 59867, upload-time = "2025-10-19T23:46:49.593Z" }, + { url = "https://files.pythonhosted.org/packages/8f/b1/ad812b1fe1cd85f6498dc3a3c9809a1e880d6108283b1735119bec217041/wrapt-2.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:c16f6d4eea98080f6659a8a7fc559d4a0a337ee66960659265cad2c8a40f7c0f", size = 63170, upload-time = "2025-10-19T23:46:46.87Z" }, + { url = "https://files.pythonhosted.org/packages/7f/29/c105b1e76650c82823c491952a7a8eafe09b78944f7a43f22d37ed860229/wrapt-2.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:52878edc13dc151c58a9966621d67163a80654bc6cff4b2e1c79fa62d0352b26", size = 60339, upload-time = "2025-10-19T23:46:47.862Z" }, + { url = "https://files.pythonhosted.org/packages/f8/38/0dd39f83163fd28326afba84e3e416656938df07e60a924ac4d992b30220/wrapt-2.0.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:79a53d86c2aff7b32cc77267e3a308365d1fcb881e74bc9cbe26f63ee90e37f0", size = 78242, upload-time = "2025-10-19T23:46:51.096Z" }, + { url = "https://files.pythonhosted.org/packages/08/ef/fa7a5c1d73f8690c712f9d2e4615700c6809942536dd3f441b9ba650a310/wrapt-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d731a4f22ed6ffa4cb551b4d2b0c24ff940c27a88edaf8e3490a5ee3a05aef71", size = 61207, upload-time = "2025-10-19T23:46:52.558Z" }, + { url = "https://files.pythonhosted.org/packages/23/d9/67cb93da492eb0a1cb17b7ed18220d059e58f00467ce6728b674d3441b3d/wrapt-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3e02ab8c0ac766a5a6e81cd3b6cc39200c69051826243182175555872522bd5a", size = 61748, upload-time = "2025-10-19T23:46:54.468Z" }, + { url = "https://files.pythonhosted.org/packages/e5/be/912bbd70cc614f491b526a1d7fe85695b283deed19287b9f32460178c54d/wrapt-2.0.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:895870602d65d7338edb3b6a717d856632ad9f14f7ff566214e4fb11f0816649", size = 120424, upload-time = "2025-10-19T23:46:57.575Z" }, + { url = "https://files.pythonhosted.org/packages/b2/e1/10df8937e7da2aa9bc3662a4b623e51a323c68f42cad7b13f0e61a700ce2/wrapt-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b9ad4fab76a0086dc364c4f17f39ad289600e73ef5c6e9ab529aff22cac1ac3", size = 122804, upload-time = "2025-10-19T23:46:59.308Z" }, + { url = "https://files.pythonhosted.org/packages/f3/60/576751b1919adab9f63168e3b5fd46c0d1565871b1cc4c2569503ccf4be6/wrapt-2.0.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e7ca0562606d7bad2736b2c18f61295d61f50cd3f4bfc51753df13614dbcce1b", size = 117398, upload-time = "2025-10-19T23:46:55.814Z" }, + { url = "https://files.pythonhosted.org/packages/ec/55/243411f360cc27bae5f8e21c16f1a8d87674c5534f4558e8a97c1e0d1c6f/wrapt-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fe089d9f5a4a3dea0108a8ae34bced114d0c4cca417bada1c5e8f42d98af9050", size = 121230, upload-time = "2025-10-19T23:47:01.347Z" }, + { url = "https://files.pythonhosted.org/packages/d6/23/2f21f692c3b3f0857cb82708ce0c341fbac55a489d4025ae4e3fd5d5de8c/wrapt-2.0.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e761f2d2f8dbc80384af3d547b522a80e67db3e319c7b02e7fd97aded0a8a678", size = 116296, upload-time = "2025-10-19T23:47:02.659Z" }, + { url = "https://files.pythonhosted.org/packages/bd/ed/678957fad212cfb1b65b2359d62f5619f5087d1d1cf296c6a996be45171c/wrapt-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:17ba1bdc52d0c783481850996aa26cea5237720769197335abea2ae6b4c23bc0", size = 119602, upload-time = "2025-10-19T23:47:03.775Z" }, + { url = "https://files.pythonhosted.org/packages/dc/e3/aeb4c3b052d3eed95e61babc20dcb1a512651e098cca4b84a6896585c06a/wrapt-2.0.0-cp314-cp314-win32.whl", hash = "sha256:f73318741b141223a4674ba96992aa2291b1b3f7a5e85cb3c2c964f86171eb45", size = 58649, upload-time = "2025-10-19T23:47:07.382Z" }, + { url = "https://files.pythonhosted.org/packages/aa/2a/a71c51cb211798405b59172c7df5789a5b934b18317223cf22e0c6f852de/wrapt-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:8e08d4edb13cafe7b3260f31d4de033f73d3205774540cf583bffaa4bec97db9", size = 60897, upload-time = "2025-10-19T23:47:04.862Z" }, + { url = "https://files.pythonhosted.org/packages/f8/a5/acc5628035d06f69e9144cca543ca54c33b42a5a23b6f1e8fa131026db89/wrapt-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:af01695c2b7bbd8d67b869d8e3de2b123a7bfbee0185bdd138c2775f75373b83", size = 59306, upload-time = "2025-10-19T23:47:05.883Z" }, + { url = "https://files.pythonhosted.org/packages/a7/e6/1318ca07d7fcee57e4592a78dacd9d5493b8ddd971c553a62904fb2c0cf2/wrapt-2.0.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:057f02c13cce7b26c79624c06a3e1c2353e6dc9708525232232f6768118042ca", size = 81987, upload-time = "2025-10-19T23:47:08.7Z" }, + { url = "https://files.pythonhosted.org/packages/e7/bf/ffac358ddf61c3923d94a8b0e7620f2af1cd1b637a0fe4963a3919aa62b7/wrapt-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:79bdd84570267f3f43d609c892ae2d30b91ee4b8614c2cbfd311a2965f1c9bdb", size = 62902, upload-time = "2025-10-19T23:47:10.248Z" }, + { url = "https://files.pythonhosted.org/packages/b5/af/387c51f9e7b544fe95d852fc94f9f3866e3f7d7d39c2ee65041752f90bc2/wrapt-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:93c8b4f4d54fd401a817abbfc9bf482aa72fd447f8adf19ce81d035b3f5c762c", size = 63635, upload-time = "2025-10-19T23:47:11.746Z" }, + { url = "https://files.pythonhosted.org/packages/7c/99/d38d8c80b9cc352531d4d539a17e3674169a5cc25a7e6e5e3c27bc29893e/wrapt-2.0.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5e09ffd31001dce71c2c2a4fc201bdba9a2f9f62b23700cf24af42266e784741", size = 152659, upload-time = "2025-10-19T23:47:15.344Z" }, + { url = "https://files.pythonhosted.org/packages/5a/2a/e154432f274e22ecf2465583386c5ceffa5e0bab3947c1c5b26cc8e7b275/wrapt-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d87c285ff04e26083c4b03546e7b74df7ba4f1f32f1dcb92e9ac13c2dbb4c379", size = 158818, upload-time = "2025-10-19T23:47:17.569Z" }, + { url = "https://files.pythonhosted.org/packages/c5/7a/3a40c453300e2898e99c27495b8109ff7cd526997d12cfb8ebd1843199a4/wrapt-2.0.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e52e50ea0a72ea48d1291cf8b8aaedcc99072d9dc5baba6b820486dcf4c67da8", size = 146113, upload-time = "2025-10-19T23:47:13.026Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e2/3116a9eade8bea2bf5eedba3fa420e3c7d193d4b047440330d8eaf1098de/wrapt-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fd4c95536975895f32571073446e614d5e2810b666b64955586dcddfd438fd3", size = 155689, upload-time = "2025-10-19T23:47:19.397Z" }, + { url = "https://files.pythonhosted.org/packages/43/1c/277d3fbe9d177830ab9e54fe9253f38455b75a22d639a4bd9fa092d55ae5/wrapt-2.0.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d6ebfe9283209220ed9de80a3e9442aab8fc2be5a9bbf8491b99e02ca9349a89", size = 144403, upload-time = "2025-10-19T23:47:20.779Z" }, + { url = "https://files.pythonhosted.org/packages/d8/37/ab6ddaf182248aac5ed925725ef4c69a510594764665ecbd95bdd4481f16/wrapt-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5d3ebd784804f146b7ea55359beb138e23cc18e5a5cc2cf26ad438723c00ce3a", size = 150307, upload-time = "2025-10-19T23:47:22.604Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d7/df9e2d8040a3af618ff9496261cf90ca4f886fd226af0f4a69ac0c020c3b/wrapt-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:9b15940ae9debc8b40b15dc57e1ce4433f7fb9d3f8761c7fab1ddd94cb999d99", size = 60557, upload-time = "2025-10-19T23:47:26.73Z" }, + { url = "https://files.pythonhosted.org/packages/b4/c2/502bd4557a3a9199ea73cc5932cf83354bd362682162f0b14164d2e90216/wrapt-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7a0efbbc06d3e2077476a04f55859819d23206600b4c33f791359a8e6fa3c362", size = 63988, upload-time = "2025-10-19T23:47:23.826Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f2/632b13942f45db7af709f346ff38b8992c8c21b004e61ab320b0dec525fe/wrapt-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:7fec8a9455c029c8cf4ff143a53b6e7c463268d42be6c17efa847ebd2f809965", size = 60584, upload-time = "2025-10-19T23:47:25.396Z" }, + { url = "https://files.pythonhosted.org/packages/00/5c/c34575f96a0a038579683c7f10fca943c15c7946037d1d254ab9db1536ec/wrapt-2.0.0-py3-none-any.whl", hash = "sha256:02482fb0df89857e35427dfb844319417e14fae05878f295ee43fa3bf3b15502", size = 43998, upload-time = "2025-10-19T23:47:52.858Z" }, +] + +[[package]] +name = "xxhash" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/02/84/30869e01909fb37a6cc7e18688ee8bf1e42d57e7e0777636bd47524c43c7/xxhash-3.6.0.tar.gz", hash = "sha256:f0162a78b13a0d7617b2845b90c763339d1f1d82bb04a4b07f4ab535cc5e05d6", size = 85160, upload-time = "2025-10-02T14:37:08.097Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/ee/f9f1d656ad168681bb0f6b092372c1e533c4416b8069b1896a175c46e484/xxhash-3.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:87ff03d7e35c61435976554477a7f4cd1704c3596a89a8300d5ce7fc83874a71", size = 32845, upload-time = "2025-10-02T14:33:51.573Z" }, + { url = "https://files.pythonhosted.org/packages/a3/b1/93508d9460b292c74a09b83d16750c52a0ead89c51eea9951cb97a60d959/xxhash-3.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f572dfd3d0e2eb1a57511831cf6341242f5a9f8298a45862d085f5b93394a27d", size = 30807, upload-time = "2025-10-02T14:33:52.964Z" }, + { url = "https://files.pythonhosted.org/packages/07/55/28c93a3662f2d200c70704efe74aab9640e824f8ce330d8d3943bf7c9b3c/xxhash-3.6.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:89952ea539566b9fed2bbd94e589672794b4286f342254fad28b149f9615fef8", size = 193786, upload-time = "2025-10-02T14:33:54.272Z" }, + { url = "https://files.pythonhosted.org/packages/c1/96/fec0be9bb4b8f5d9c57d76380a366f31a1781fb802f76fc7cda6c84893c7/xxhash-3.6.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e6f2ffb07a50b52465a1032c3cf1f4a5683f944acaca8a134a2f23674c2058", size = 212830, upload-time = "2025-10-02T14:33:55.706Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a0/c706845ba77b9611f81fd2e93fad9859346b026e8445e76f8c6fd057cc6d/xxhash-3.6.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b5b848ad6c16d308c3ac7ad4ba6bede80ed5df2ba8ed382f8932df63158dd4b2", size = 211606, upload-time = "2025-10-02T14:33:57.133Z" }, + { url = "https://files.pythonhosted.org/packages/67/1e/164126a2999e5045f04a69257eea946c0dc3e86541b400d4385d646b53d7/xxhash-3.6.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a034590a727b44dd8ac5914236a7b8504144447a9682586c3327e935f33ec8cc", size = 444872, upload-time = "2025-10-02T14:33:58.446Z" }, + { url = "https://files.pythonhosted.org/packages/2d/4b/55ab404c56cd70a2cf5ecfe484838865d0fea5627365c6c8ca156bd09c8f/xxhash-3.6.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a8f1972e75ebdd161d7896743122834fe87378160c20e97f8b09166213bf8cc", size = 193217, upload-time = "2025-10-02T14:33:59.724Z" }, + { url = "https://files.pythonhosted.org/packages/45/e6/52abf06bac316db33aa269091ae7311bd53cfc6f4b120ae77bac1b348091/xxhash-3.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ee34327b187f002a596d7b167ebc59a1b729e963ce645964bbc050d2f1b73d07", size = 210139, upload-time = "2025-10-02T14:34:02.041Z" }, + { url = "https://files.pythonhosted.org/packages/34/37/db94d490b8691236d356bc249c08819cbcef9273a1a30acf1254ff9ce157/xxhash-3.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:339f518c3c7a850dd033ab416ea25a692759dc7478a71131fe8869010d2b75e4", size = 197669, upload-time = "2025-10-02T14:34:03.664Z" }, + { url = "https://files.pythonhosted.org/packages/b7/36/c4f219ef4a17a4f7a64ed3569bc2b5a9c8311abdb22249ac96093625b1a4/xxhash-3.6.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:bf48889c9630542d4709192578aebbd836177c9f7a4a2778a7d6340107c65f06", size = 210018, upload-time = "2025-10-02T14:34:05.325Z" }, + { url = "https://files.pythonhosted.org/packages/fd/06/bfac889a374fc2fc439a69223d1750eed2e18a7db8514737ab630534fa08/xxhash-3.6.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:5576b002a56207f640636056b4160a378fe36a58db73ae5c27a7ec8db35f71d4", size = 413058, upload-time = "2025-10-02T14:34:06.925Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d1/555d8447e0dd32ad0930a249a522bb2e289f0d08b6b16204cfa42c1f5a0c/xxhash-3.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af1f3278bd02814d6dedc5dec397993b549d6f16c19379721e5a1d31e132c49b", size = 190628, upload-time = "2025-10-02T14:34:08.669Z" }, + { url = "https://files.pythonhosted.org/packages/d1/15/8751330b5186cedc4ed4b597989882ea05e0408b53fa47bcb46a6125bfc6/xxhash-3.6.0-cp310-cp310-win32.whl", hash = "sha256:aed058764db109dc9052720da65fafe84873b05eb8b07e5e653597951af57c3b", size = 30577, upload-time = "2025-10-02T14:34:10.234Z" }, + { url = "https://files.pythonhosted.org/packages/bb/cc/53f87e8b5871a6eb2ff7e89c48c66093bda2be52315a8161ddc54ea550c4/xxhash-3.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:e82da5670f2d0d98950317f82a0e4a0197150ff19a6df2ba40399c2a3b9ae5fb", size = 31487, upload-time = "2025-10-02T14:34:11.618Z" }, + { url = "https://files.pythonhosted.org/packages/9f/00/60f9ea3bb697667a14314d7269956f58bf56bb73864f8f8d52a3c2535e9a/xxhash-3.6.0-cp310-cp310-win_arm64.whl", hash = "sha256:4a082ffff8c6ac07707fb6b671caf7c6e020c75226c561830b73d862060f281d", size = 27863, upload-time = "2025-10-02T14:34:12.619Z" }, + { url = "https://files.pythonhosted.org/packages/17/d4/cc2f0400e9154df4b9964249da78ebd72f318e35ccc425e9f403c392f22a/xxhash-3.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b47bbd8cf2d72797f3c2772eaaac0ded3d3af26481a26d7d7d41dc2d3c46b04a", size = 32844, upload-time = "2025-10-02T14:34:14.037Z" }, + { url = "https://files.pythonhosted.org/packages/5e/ec/1cc11cd13e26ea8bc3cb4af4eaadd8d46d5014aebb67be3f71fb0b68802a/xxhash-3.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2b6821e94346f96db75abaa6e255706fb06ebd530899ed76d32cd99f20dc52fa", size = 30809, upload-time = "2025-10-02T14:34:15.484Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/19fe357ea348d98ca22f456f75a30ac0916b51c753e1f8b2e0e6fb884cce/xxhash-3.6.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d0a9751f71a1a65ce3584e9cae4467651c7e70c9d31017fa57574583a4540248", size = 194665, upload-time = "2025-10-02T14:34:16.541Z" }, + { url = "https://files.pythonhosted.org/packages/90/3b/d1f1a8f5442a5fd8beedae110c5af7604dc37349a8e16519c13c19a9a2de/xxhash-3.6.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b29ee68625ab37b04c0b40c3fafdf24d2f75ccd778333cfb698f65f6c463f62", size = 213550, upload-time = "2025-10-02T14:34:17.878Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ef/3a9b05eb527457d5db13a135a2ae1a26c80fecd624d20f3e8dcc4cb170f3/xxhash-3.6.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6812c25fe0d6c36a46ccb002f40f27ac903bf18af9f6dd8f9669cb4d176ab18f", size = 212384, upload-time = "2025-10-02T14:34:19.182Z" }, + { url = "https://files.pythonhosted.org/packages/0f/18/ccc194ee698c6c623acbf0f8c2969811a8a4b6185af5e824cd27b9e4fd3e/xxhash-3.6.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4ccbff013972390b51a18ef1255ef5ac125c92dc9143b2d1909f59abc765540e", size = 445749, upload-time = "2025-10-02T14:34:20.659Z" }, + { url = "https://files.pythonhosted.org/packages/a5/86/cf2c0321dc3940a7aa73076f4fd677a0fb3e405cb297ead7d864fd90847e/xxhash-3.6.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:297b7fbf86c82c550e12e8fb71968b3f033d27b874276ba3624ea868c11165a8", size = 193880, upload-time = "2025-10-02T14:34:22.431Z" }, + { url = "https://files.pythonhosted.org/packages/82/fb/96213c8560e6f948a1ecc9a7613f8032b19ee45f747f4fca4eb31bb6d6ed/xxhash-3.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dea26ae1eb293db089798d3973a5fc928a18fdd97cc8801226fae705b02b14b0", size = 210912, upload-time = "2025-10-02T14:34:23.937Z" }, + { url = "https://files.pythonhosted.org/packages/40/aa/4395e669b0606a096d6788f40dbdf2b819d6773aa290c19e6e83cbfc312f/xxhash-3.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7a0b169aafb98f4284f73635a8e93f0735f9cbde17bd5ec332480484241aaa77", size = 198654, upload-time = "2025-10-02T14:34:25.644Z" }, + { url = "https://files.pythonhosted.org/packages/67/74/b044fcd6b3d89e9b1b665924d85d3f400636c23590226feb1eb09e1176ce/xxhash-3.6.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:08d45aef063a4531b785cd72de4887766d01dc8f362a515693df349fdb825e0c", size = 210867, upload-time = "2025-10-02T14:34:27.203Z" }, + { url = "https://files.pythonhosted.org/packages/bc/fd/3ce73bf753b08cb19daee1eb14aa0d7fe331f8da9c02dd95316ddfe5275e/xxhash-3.6.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:929142361a48ee07f09121fe9e96a84950e8d4df3bb298ca5d88061969f34d7b", size = 414012, upload-time = "2025-10-02T14:34:28.409Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b3/5a4241309217c5c876f156b10778f3ab3af7ba7e3259e6d5f5c7d0129eb2/xxhash-3.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:51312c768403d8540487dbbfb557454cfc55589bbde6424456951f7fcd4facb3", size = 191409, upload-time = "2025-10-02T14:34:29.696Z" }, + { url = "https://files.pythonhosted.org/packages/c0/01/99bfbc15fb9abb9a72b088c1d95219fc4782b7d01fc835bd5744d66dd0b8/xxhash-3.6.0-cp311-cp311-win32.whl", hash = "sha256:d1927a69feddc24c987b337ce81ac15c4720955b667fe9b588e02254b80446fd", size = 30574, upload-time = "2025-10-02T14:34:31.028Z" }, + { url = "https://files.pythonhosted.org/packages/65/79/9d24d7f53819fe301b231044ea362ce64e86c74f6e8c8e51320de248b3e5/xxhash-3.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:26734cdc2d4ffe449b41d186bbeac416f704a482ed835d375a5c0cb02bc63fef", size = 31481, upload-time = "2025-10-02T14:34:32.062Z" }, + { url = "https://files.pythonhosted.org/packages/30/4e/15cd0e3e8772071344eab2961ce83f6e485111fed8beb491a3f1ce100270/xxhash-3.6.0-cp311-cp311-win_arm64.whl", hash = "sha256:d72f67ef8bf36e05f5b6c65e8524f265bd61071471cd4cf1d36743ebeeeb06b7", size = 27861, upload-time = "2025-10-02T14:34:33.555Z" }, + { url = "https://files.pythonhosted.org/packages/9a/07/d9412f3d7d462347e4511181dea65e47e0d0e16e26fbee2ea86a2aefb657/xxhash-3.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:01362c4331775398e7bb34e3ab403bc9ee9f7c497bc7dee6272114055277dd3c", size = 32744, upload-time = "2025-10-02T14:34:34.622Z" }, + { url = "https://files.pythonhosted.org/packages/79/35/0429ee11d035fc33abe32dca1b2b69e8c18d236547b9a9b72c1929189b9a/xxhash-3.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b7b2df81a23f8cb99656378e72501b2cb41b1827c0f5a86f87d6b06b69f9f204", size = 30816, upload-time = "2025-10-02T14:34:36.043Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f2/57eb99aa0f7d98624c0932c5b9a170e1806406cdbcdb510546634a1359e0/xxhash-3.6.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:dc94790144e66b14f67b10ac8ed75b39ca47536bf8800eb7c24b50271ea0c490", size = 194035, upload-time = "2025-10-02T14:34:37.354Z" }, + { url = "https://files.pythonhosted.org/packages/4c/ed/6224ba353690d73af7a3f1c7cdb1fc1b002e38f783cb991ae338e1eb3d79/xxhash-3.6.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:93f107c673bccf0d592cdba077dedaf52fe7f42dcd7676eba1f6d6f0c3efffd2", size = 212914, upload-time = "2025-10-02T14:34:38.6Z" }, + { url = "https://files.pythonhosted.org/packages/38/86/fb6b6130d8dd6b8942cc17ab4d90e223653a89aa32ad2776f8af7064ed13/xxhash-3.6.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2aa5ee3444c25b69813663c9f8067dcfaa2e126dc55e8dddf40f4d1c25d7effa", size = 212163, upload-time = "2025-10-02T14:34:39.872Z" }, + { url = "https://files.pythonhosted.org/packages/ee/dc/e84875682b0593e884ad73b2d40767b5790d417bde603cceb6878901d647/xxhash-3.6.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7f99123f0e1194fa59cc69ad46dbae2e07becec5df50a0509a808f90a0f03f0", size = 445411, upload-time = "2025-10-02T14:34:41.569Z" }, + { url = "https://files.pythonhosted.org/packages/11/4f/426f91b96701ec2f37bb2b8cec664eff4f658a11f3fa9d94f0a887ea6d2b/xxhash-3.6.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49e03e6fe2cac4a1bc64952dd250cf0dbc5ef4ebb7b8d96bce82e2de163c82a2", size = 193883, upload-time = "2025-10-02T14:34:43.249Z" }, + { url = "https://files.pythonhosted.org/packages/53/5a/ddbb83eee8e28b778eacfc5a85c969673e4023cdeedcfcef61f36731610b/xxhash-3.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bd17fede52a17a4f9a7bc4472a5867cb0b160deeb431795c0e4abe158bc784e9", size = 210392, upload-time = "2025-10-02T14:34:45.042Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c2/ff69efd07c8c074ccdf0a4f36fcdd3d27363665bcdf4ba399abebe643465/xxhash-3.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6fb5f5476bef678f69db04f2bd1efbed3030d2aba305b0fc1773645f187d6a4e", size = 197898, upload-time = "2025-10-02T14:34:46.302Z" }, + { url = "https://files.pythonhosted.org/packages/58/ca/faa05ac19b3b622c7c9317ac3e23954187516298a091eb02c976d0d3dd45/xxhash-3.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:843b52f6d88071f87eba1631b684fcb4b2068cd2180a0224122fe4ef011a9374", size = 210655, upload-time = "2025-10-02T14:34:47.571Z" }, + { url = "https://files.pythonhosted.org/packages/d4/7a/06aa7482345480cc0cb597f5c875b11a82c3953f534394f620b0be2f700c/xxhash-3.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7d14a6cfaf03b1b6f5f9790f76880601ccc7896aff7ab9cd8978a939c1eb7e0d", size = 414001, upload-time = "2025-10-02T14:34:49.273Z" }, + { url = "https://files.pythonhosted.org/packages/23/07/63ffb386cd47029aa2916b3d2f454e6cc5b9f5c5ada3790377d5430084e7/xxhash-3.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:418daf3db71e1413cfe211c2f9a528456936645c17f46b5204705581a45390ae", size = 191431, upload-time = "2025-10-02T14:34:50.798Z" }, + { url = "https://files.pythonhosted.org/packages/0f/93/14fde614cadb4ddf5e7cebf8918b7e8fac5ae7861c1875964f17e678205c/xxhash-3.6.0-cp312-cp312-win32.whl", hash = "sha256:50fc255f39428a27299c20e280d6193d8b63b8ef8028995323bf834a026b4fbb", size = 30617, upload-time = "2025-10-02T14:34:51.954Z" }, + { url = "https://files.pythonhosted.org/packages/13/5d/0d125536cbe7565a83d06e43783389ecae0c0f2ed037b48ede185de477c0/xxhash-3.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:c0f2ab8c715630565ab8991b536ecded9416d615538be8ecddce43ccf26cbc7c", size = 31534, upload-time = "2025-10-02T14:34:53.276Z" }, + { url = "https://files.pythonhosted.org/packages/54/85/6ec269b0952ec7e36ba019125982cf11d91256a778c7c3f98a4c5043d283/xxhash-3.6.0-cp312-cp312-win_arm64.whl", hash = "sha256:eae5c13f3bc455a3bbb68bdc513912dc7356de7e2280363ea235f71f54064829", size = 27876, upload-time = "2025-10-02T14:34:54.371Z" }, + { url = "https://files.pythonhosted.org/packages/33/76/35d05267ac82f53ae9b0e554da7c5e281ee61f3cad44c743f0fcd354f211/xxhash-3.6.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:599e64ba7f67472481ceb6ee80fa3bd828fd61ba59fb11475572cc5ee52b89ec", size = 32738, upload-time = "2025-10-02T14:34:55.839Z" }, + { url = "https://files.pythonhosted.org/packages/31/a8/3fbce1cd96534a95e35d5120637bf29b0d7f5d8fa2f6374e31b4156dd419/xxhash-3.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7d8b8aaa30fca4f16f0c84a5c8d7ddee0e25250ec2796c973775373257dde8f1", size = 30821, upload-time = "2025-10-02T14:34:57.219Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ea/d387530ca7ecfa183cb358027f1833297c6ac6098223fd14f9782cd0015c/xxhash-3.6.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d597acf8506d6e7101a4a44a5e428977a51c0fadbbfd3c39650cca9253f6e5a6", size = 194127, upload-time = "2025-10-02T14:34:59.21Z" }, + { url = "https://files.pythonhosted.org/packages/ba/0c/71435dcb99874b09a43b8d7c54071e600a7481e42b3e3ce1eb5226a5711a/xxhash-3.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:858dc935963a33bc33490128edc1c12b0c14d9c7ebaa4e387a7869ecc4f3e263", size = 212975, upload-time = "2025-10-02T14:35:00.816Z" }, + { url = "https://files.pythonhosted.org/packages/84/7a/c2b3d071e4bb4a90b7057228a99b10d51744878f4a8a6dd643c8bd897620/xxhash-3.6.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba284920194615cb8edf73bf52236ce2e1664ccd4a38fdb543506413529cc546", size = 212241, upload-time = "2025-10-02T14:35:02.207Z" }, + { url = "https://files.pythonhosted.org/packages/81/5f/640b6eac0128e215f177df99eadcd0f1b7c42c274ab6a394a05059694c5a/xxhash-3.6.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b54219177f6c6674d5378bd862c6aedf64725f70dd29c472eaae154df1a2e89", size = 445471, upload-time = "2025-10-02T14:35:03.61Z" }, + { url = "https://files.pythonhosted.org/packages/5e/1e/3c3d3ef071b051cc3abbe3721ffb8365033a172613c04af2da89d5548a87/xxhash-3.6.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42c36dd7dbad2f5238950c377fcbf6811b1cdb1c444fab447960030cea60504d", size = 193936, upload-time = "2025-10-02T14:35:05.013Z" }, + { url = "https://files.pythonhosted.org/packages/2c/bd/4a5f68381939219abfe1c22a9e3a5854a4f6f6f3c4983a87d255f21f2e5d/xxhash-3.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f22927652cba98c44639ffdc7aaf35828dccf679b10b31c4ad72a5b530a18eb7", size = 210440, upload-time = "2025-10-02T14:35:06.239Z" }, + { url = "https://files.pythonhosted.org/packages/eb/37/b80fe3d5cfb9faff01a02121a0f4d565eb7237e9e5fc66e73017e74dcd36/xxhash-3.6.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b45fad44d9c5c119e9c6fbf2e1c656a46dc68e280275007bbfd3d572b21426db", size = 197990, upload-time = "2025-10-02T14:35:07.735Z" }, + { url = "https://files.pythonhosted.org/packages/d7/fd/2c0a00c97b9e18f72e1f240ad4e8f8a90fd9d408289ba9c7c495ed7dc05c/xxhash-3.6.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6f2580ffab1a8b68ef2b901cde7e55fa8da5e4be0977c68f78fc80f3c143de42", size = 210689, upload-time = "2025-10-02T14:35:09.438Z" }, + { url = "https://files.pythonhosted.org/packages/93/86/5dd8076a926b9a95db3206aba20d89a7fc14dd5aac16e5c4de4b56033140/xxhash-3.6.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:40c391dd3cd041ebc3ffe6f2c862f402e306eb571422e0aa918d8070ba31da11", size = 414068, upload-time = "2025-10-02T14:35:11.162Z" }, + { url = "https://files.pythonhosted.org/packages/af/3c/0bb129170ee8f3650f08e993baee550a09593462a5cddd8e44d0011102b1/xxhash-3.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f205badabde7aafd1a31e8ca2a3e5a763107a71c397c4481d6a804eb5063d8bd", size = 191495, upload-time = "2025-10-02T14:35:12.971Z" }, + { url = "https://files.pythonhosted.org/packages/e9/3a/6797e0114c21d1725e2577508e24006fd7ff1d8c0c502d3b52e45c1771d8/xxhash-3.6.0-cp313-cp313-win32.whl", hash = "sha256:2577b276e060b73b73a53042ea5bd5203d3e6347ce0d09f98500f418a9fcf799", size = 30620, upload-time = "2025-10-02T14:35:14.129Z" }, + { url = "https://files.pythonhosted.org/packages/86/15/9bc32671e9a38b413a76d24722a2bf8784a132c043063a8f5152d390b0f9/xxhash-3.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:757320d45d2fbcce8f30c42a6b2f47862967aea7bf458b9625b4bbe7ee390392", size = 31542, upload-time = "2025-10-02T14:35:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/39/c5/cc01e4f6188656e56112d6a8e0dfe298a16934b8c47a247236549a3f7695/xxhash-3.6.0-cp313-cp313-win_arm64.whl", hash = "sha256:457b8f85dec5825eed7b69c11ae86834a018b8e3df5e77783c999663da2f96d6", size = 27880, upload-time = "2025-10-02T14:35:16.315Z" }, + { url = "https://files.pythonhosted.org/packages/f3/30/25e5321c8732759e930c555176d37e24ab84365482d257c3b16362235212/xxhash-3.6.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a42e633d75cdad6d625434e3468126c73f13f7584545a9cf34e883aa1710e702", size = 32956, upload-time = "2025-10-02T14:35:17.413Z" }, + { url = "https://files.pythonhosted.org/packages/9f/3c/0573299560d7d9f8ab1838f1efc021a280b5ae5ae2e849034ef3dee18810/xxhash-3.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:568a6d743219e717b07b4e03b0a828ce593833e498c3b64752e0f5df6bfe84db", size = 31072, upload-time = "2025-10-02T14:35:18.844Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1c/52d83a06e417cd9d4137722693424885cc9878249beb3a7c829e74bf7ce9/xxhash-3.6.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bec91b562d8012dae276af8025a55811b875baace6af510412a5e58e3121bc54", size = 196409, upload-time = "2025-10-02T14:35:20.31Z" }, + { url = "https://files.pythonhosted.org/packages/e3/8e/c6d158d12a79bbd0b878f8355432075fc82759e356ab5a111463422a239b/xxhash-3.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78e7f2f4c521c30ad5e786fdd6bae89d47a32672a80195467b5de0480aa97b1f", size = 215736, upload-time = "2025-10-02T14:35:21.616Z" }, + { url = "https://files.pythonhosted.org/packages/bc/68/c4c80614716345d55071a396cf03d06e34b5f4917a467faf43083c995155/xxhash-3.6.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3ed0df1b11a79856df5ffcab572cbd6b9627034c1c748c5566fa79df9048a7c5", size = 214833, upload-time = "2025-10-02T14:35:23.32Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e9/ae27c8ffec8b953efa84c7c4a6c6802c263d587b9fc0d6e7cea64e08c3af/xxhash-3.6.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0e4edbfc7d420925b0dd5e792478ed393d6e75ff8fc219a6546fb446b6a417b1", size = 448348, upload-time = "2025-10-02T14:35:25.111Z" }, + { url = "https://files.pythonhosted.org/packages/d7/6b/33e21afb1b5b3f46b74b6bd1913639066af218d704cc0941404ca717fc57/xxhash-3.6.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fba27a198363a7ef87f8c0f6b171ec36b674fe9053742c58dd7e3201c1ab30ee", size = 196070, upload-time = "2025-10-02T14:35:26.586Z" }, + { url = "https://files.pythonhosted.org/packages/96/b6/fcabd337bc5fa624e7203aa0fa7d0c49eed22f72e93229431752bddc83d9/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:794fe9145fe60191c6532fa95063765529770edcdd67b3d537793e8004cabbfd", size = 212907, upload-time = "2025-10-02T14:35:28.087Z" }, + { url = "https://files.pythonhosted.org/packages/4b/d3/9ee6160e644d660fcf176c5825e61411c7f62648728f69c79ba237250143/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6105ef7e62b5ac73a837778efc331a591d8442f8ef5c7e102376506cb4ae2729", size = 200839, upload-time = "2025-10-02T14:35:29.857Z" }, + { url = "https://files.pythonhosted.org/packages/0d/98/e8de5baa5109394baf5118f5e72ab21a86387c4f89b0e77ef3e2f6b0327b/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:f01375c0e55395b814a679b3eea205db7919ac2af213f4a6682e01220e5fe292", size = 213304, upload-time = "2025-10-02T14:35:31.222Z" }, + { url = "https://files.pythonhosted.org/packages/7b/1d/71056535dec5c3177eeb53e38e3d367dd1d16e024e63b1cee208d572a033/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d706dca2d24d834a4661619dcacf51a75c16d65985718d6a7d73c1eeeb903ddf", size = 416930, upload-time = "2025-10-02T14:35:32.517Z" }, + { url = "https://files.pythonhosted.org/packages/dc/6c/5cbde9de2cd967c322e651c65c543700b19e7ae3e0aae8ece3469bf9683d/xxhash-3.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5f059d9faeacd49c0215d66f4056e1326c80503f51a1532ca336a385edadd033", size = 193787, upload-time = "2025-10-02T14:35:33.827Z" }, + { url = "https://files.pythonhosted.org/packages/19/fa/0172e350361d61febcea941b0cc541d6e6c8d65d153e85f850a7b256ff8a/xxhash-3.6.0-cp313-cp313t-win32.whl", hash = "sha256:1244460adc3a9be84731d72b8e80625788e5815b68da3da8b83f78115a40a7ec", size = 30916, upload-time = "2025-10-02T14:35:35.107Z" }, + { url = "https://files.pythonhosted.org/packages/ad/e6/e8cf858a2b19d6d45820f072eff1bea413910592ff17157cabc5f1227a16/xxhash-3.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b1e420ef35c503869c4064f4a2f2b08ad6431ab7b229a05cce39d74268bca6b8", size = 31799, upload-time = "2025-10-02T14:35:36.165Z" }, + { url = "https://files.pythonhosted.org/packages/56/15/064b197e855bfb7b343210e82490ae672f8bc7cdf3ddb02e92f64304ee8a/xxhash-3.6.0-cp313-cp313t-win_arm64.whl", hash = "sha256:ec44b73a4220623235f67a996c862049f375df3b1052d9899f40a6382c32d746", size = 28044, upload-time = "2025-10-02T14:35:37.195Z" }, + { url = "https://files.pythonhosted.org/packages/7e/5e/0138bc4484ea9b897864d59fce9be9086030825bc778b76cb5a33a906d37/xxhash-3.6.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a40a3d35b204b7cc7643cbcf8c9976d818cb47befcfac8bbefec8038ac363f3e", size = 32754, upload-time = "2025-10-02T14:35:38.245Z" }, + { url = "https://files.pythonhosted.org/packages/18/d7/5dac2eb2ec75fd771957a13e5dda560efb2176d5203f39502a5fc571f899/xxhash-3.6.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a54844be970d3fc22630b32d515e79a90d0a3ddb2644d8d7402e3c4c8da61405", size = 30846, upload-time = "2025-10-02T14:35:39.6Z" }, + { url = "https://files.pythonhosted.org/packages/fe/71/8bc5be2bb00deb5682e92e8da955ebe5fa982da13a69da5a40a4c8db12fb/xxhash-3.6.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:016e9190af8f0a4e3741343777710e3d5717427f175adfdc3e72508f59e2a7f3", size = 194343, upload-time = "2025-10-02T14:35:40.69Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3b/52badfb2aecec2c377ddf1ae75f55db3ba2d321c5e164f14461c90837ef3/xxhash-3.6.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f6f72232f849eb9d0141e2ebe2677ece15adfd0fa599bc058aad83c714bb2c6", size = 213074, upload-time = "2025-10-02T14:35:42.29Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2b/ae46b4e9b92e537fa30d03dbc19cdae57ed407e9c26d163895e968e3de85/xxhash-3.6.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:63275a8aba7865e44b1813d2177e0f5ea7eadad3dd063a21f7cf9afdc7054063", size = 212388, upload-time = "2025-10-02T14:35:43.929Z" }, + { url = "https://files.pythonhosted.org/packages/f5/80/49f88d3afc724b4ac7fbd664c8452d6db51b49915be48c6982659e0e7942/xxhash-3.6.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cd01fa2aa00d8b017c97eb46b9a794fbdca53fc14f845f5a328c71254b0abb7", size = 445614, upload-time = "2025-10-02T14:35:45.216Z" }, + { url = "https://files.pythonhosted.org/packages/ed/ba/603ce3961e339413543d8cd44f21f2c80e2a7c5cfe692a7b1f2cccf58f3c/xxhash-3.6.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0226aa89035b62b6a86d3c68df4d7c1f47a342b8683da2b60cedcddb46c4d95b", size = 194024, upload-time = "2025-10-02T14:35:46.959Z" }, + { url = "https://files.pythonhosted.org/packages/78/d1/8e225ff7113bf81545cfdcd79eef124a7b7064a0bba53605ff39590b95c2/xxhash-3.6.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c6e193e9f56e4ca4923c61238cdaced324f0feac782544eb4c6d55ad5cc99ddd", size = 210541, upload-time = "2025-10-02T14:35:48.301Z" }, + { url = "https://files.pythonhosted.org/packages/6f/58/0f89d149f0bad89def1a8dd38feb50ccdeb643d9797ec84707091d4cb494/xxhash-3.6.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9176dcaddf4ca963d4deb93866d739a343c01c969231dbe21680e13a5d1a5bf0", size = 198305, upload-time = "2025-10-02T14:35:49.584Z" }, + { url = "https://files.pythonhosted.org/packages/11/38/5eab81580703c4df93feb5f32ff8fa7fe1e2c51c1f183ee4e48d4bb9d3d7/xxhash-3.6.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c1ce4009c97a752e682b897aa99aef84191077a9433eb237774689f14f8ec152", size = 210848, upload-time = "2025-10-02T14:35:50.877Z" }, + { url = "https://files.pythonhosted.org/packages/5e/6b/953dc4b05c3ce678abca756416e4c130d2382f877a9c30a20d08ee6a77c0/xxhash-3.6.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:8cb2f4f679b01513b7adbb9b1b2f0f9cdc31b70007eaf9d59d0878809f385b11", size = 414142, upload-time = "2025-10-02T14:35:52.15Z" }, + { url = "https://files.pythonhosted.org/packages/08/a9/238ec0d4e81a10eb5026d4a6972677cbc898ba6c8b9dbaec12ae001b1b35/xxhash-3.6.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:653a91d7c2ab54a92c19ccf43508b6a555440b9be1bc8be553376778be7f20b5", size = 191547, upload-time = "2025-10-02T14:35:53.547Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ee/3cf8589e06c2164ac77c3bf0aa127012801128f1feebf2a079272da5737c/xxhash-3.6.0-cp314-cp314-win32.whl", hash = "sha256:a756fe893389483ee8c394d06b5ab765d96e68fbbfe6fde7aa17e11f5720559f", size = 31214, upload-time = "2025-10-02T14:35:54.746Z" }, + { url = "https://files.pythonhosted.org/packages/02/5d/a19552fbc6ad4cb54ff953c3908bbc095f4a921bc569433d791f755186f1/xxhash-3.6.0-cp314-cp314-win_amd64.whl", hash = "sha256:39be8e4e142550ef69629c9cd71b88c90e9a5db703fecbcf265546d9536ca4ad", size = 32290, upload-time = "2025-10-02T14:35:55.791Z" }, + { url = "https://files.pythonhosted.org/packages/b1/11/dafa0643bc30442c887b55baf8e73353a344ee89c1901b5a5c54a6c17d39/xxhash-3.6.0-cp314-cp314-win_arm64.whl", hash = "sha256:25915e6000338999236f1eb68a02a32c3275ac338628a7eaa5a269c401995679", size = 28795, upload-time = "2025-10-02T14:35:57.162Z" }, + { url = "https://files.pythonhosted.org/packages/2c/db/0e99732ed7f64182aef4a6fb145e1a295558deec2a746265dcdec12d191e/xxhash-3.6.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c5294f596a9017ca5a3e3f8884c00b91ab2ad2933cf288f4923c3fd4346cf3d4", size = 32955, upload-time = "2025-10-02T14:35:58.267Z" }, + { url = "https://files.pythonhosted.org/packages/55/f4/2a7c3c68e564a099becfa44bb3d398810cc0ff6749b0d3cb8ccb93f23c14/xxhash-3.6.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1cf9dcc4ab9cff01dfbba78544297a3a01dafd60f3bde4e2bfd016cf7e4ddc67", size = 31072, upload-time = "2025-10-02T14:35:59.382Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d9/72a29cddc7250e8a5819dad5d466facb5dc4c802ce120645630149127e73/xxhash-3.6.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:01262da8798422d0685f7cef03b2bd3f4f46511b02830861df548d7def4402ad", size = 196579, upload-time = "2025-10-02T14:36:00.838Z" }, + { url = "https://files.pythonhosted.org/packages/63/93/b21590e1e381040e2ca305a884d89e1c345b347404f7780f07f2cdd47ef4/xxhash-3.6.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51a73fb7cb3a3ead9f7a8b583ffd9b8038e277cdb8cb87cf890e88b3456afa0b", size = 215854, upload-time = "2025-10-02T14:36:02.207Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b8/edab8a7d4fa14e924b29be877d54155dcbd8b80be85ea00d2be3413a9ed4/xxhash-3.6.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b9c6df83594f7df8f7f708ce5ebeacfc69f72c9fbaaababf6cf4758eaada0c9b", size = 214965, upload-time = "2025-10-02T14:36:03.507Z" }, + { url = "https://files.pythonhosted.org/packages/27/67/dfa980ac7f0d509d54ea0d5a486d2bb4b80c3f1bb22b66e6a05d3efaf6c0/xxhash-3.6.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:627f0af069b0ea56f312fd5189001c24578868643203bca1abbc2c52d3a6f3ca", size = 448484, upload-time = "2025-10-02T14:36:04.828Z" }, + { url = "https://files.pythonhosted.org/packages/8c/63/8ffc2cc97e811c0ca5d00ab36604b3ea6f4254f20b7bc658ca825ce6c954/xxhash-3.6.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa912c62f842dfd013c5f21a642c9c10cd9f4c4e943e0af83618b4a404d9091a", size = 196162, upload-time = "2025-10-02T14:36:06.182Z" }, + { url = "https://files.pythonhosted.org/packages/4b/77/07f0e7a3edd11a6097e990f6e5b815b6592459cb16dae990d967693e6ea9/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b465afd7909db30168ab62afe40b2fcf79eedc0b89a6c0ab3123515dc0df8b99", size = 213007, upload-time = "2025-10-02T14:36:07.733Z" }, + { url = "https://files.pythonhosted.org/packages/ae/d8/bc5fa0d152837117eb0bef6f83f956c509332ce133c91c63ce07ee7c4873/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a881851cf38b0a70e7c4d3ce81fc7afd86fbc2a024f4cfb2a97cf49ce04b75d3", size = 200956, upload-time = "2025-10-02T14:36:09.106Z" }, + { url = "https://files.pythonhosted.org/packages/26/a5/d749334130de9411783873e9b98ecc46688dad5db64ca6e04b02acc8b473/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9b3222c686a919a0f3253cfc12bb118b8b103506612253b5baeaac10d8027cf6", size = 213401, upload-time = "2025-10-02T14:36:10.585Z" }, + { url = "https://files.pythonhosted.org/packages/89/72/abed959c956a4bfc72b58c0384bb7940663c678127538634d896b1195c10/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:c5aa639bc113e9286137cec8fadc20e9cd732b2cc385c0b7fa673b84fc1f2a93", size = 417083, upload-time = "2025-10-02T14:36:12.276Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b3/62fd2b586283b7d7d665fb98e266decadf31f058f1cf6c478741f68af0cb/xxhash-3.6.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5c1343d49ac102799905e115aee590183c3921d475356cb24b4de29a4bc56518", size = 193913, upload-time = "2025-10-02T14:36:14.025Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/c19c42c5b3f5a4aad748a6d5b4f23df3bed7ee5445accc65a0fb3ff03953/xxhash-3.6.0-cp314-cp314t-win32.whl", hash = "sha256:5851f033c3030dd95c086b4a36a2683c2ff4a799b23af60977188b057e467119", size = 31586, upload-time = "2025-10-02T14:36:15.603Z" }, + { url = "https://files.pythonhosted.org/packages/03/d6/4cc450345be9924fd5dc8c590ceda1db5b43a0a889587b0ae81a95511360/xxhash-3.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0444e7967dac37569052d2409b00a8860c2135cff05502df4da80267d384849f", size = 32526, upload-time = "2025-10-02T14:36:16.708Z" }, + { url = "https://files.pythonhosted.org/packages/0f/c9/7243eb3f9eaabd1a88a5a5acadf06df2d83b100c62684b7425c6a11bcaa8/xxhash-3.6.0-cp314-cp314t-win_arm64.whl", hash = "sha256:bb79b1e63f6fd84ec778a4b1916dfe0a7c3fdb986c06addd5db3a0d413819d95", size = 28898, upload-time = "2025-10-02T14:36:17.843Z" }, + { url = "https://files.pythonhosted.org/packages/93/1e/8aec23647a34a249f62e2398c42955acd9b4c6ed5cf08cbea94dc46f78d2/xxhash-3.6.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0f7b7e2ec26c1666ad5fc9dbfa426a6a3367ceaf79db5dd76264659d509d73b0", size = 30662, upload-time = "2025-10-02T14:37:01.743Z" }, + { url = "https://files.pythonhosted.org/packages/b8/0b/b14510b38ba91caf43006209db846a696ceea6a847a0c9ba0a5b1adc53d6/xxhash-3.6.0-pp311-pypy311_pp73-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5dc1e14d14fa0f5789ec29a7062004b5933964bb9b02aae6622b8f530dc40296", size = 41056, upload-time = "2025-10-02T14:37:02.879Z" }, + { url = "https://files.pythonhosted.org/packages/50/55/15a7b8a56590e66ccd374bbfa3f9ffc45b810886c8c3b614e3f90bd2367c/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:881b47fc47e051b37d94d13e7455131054b56749b91b508b0907eb07900d1c13", size = 36251, upload-time = "2025-10-02T14:37:04.44Z" }, + { url = "https://files.pythonhosted.org/packages/62/b2/5ac99a041a29e58e95f907876b04f7067a0242cb85b5f39e726153981503/xxhash-3.6.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6dc31591899f5e5666f04cc2e529e69b4072827085c1ef15294d91a004bc1bd", size = 32481, upload-time = "2025-10-02T14:37:05.869Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d9/8d95e906764a386a3d3b596f3c68bb63687dfca806373509f51ce8eea81f/xxhash-3.6.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:15e0dac10eb9309508bfc41f7f9deaa7755c69e35af835db9cb10751adebc35d", size = 31565, upload-time = "2025-10-02T14:37:06.966Z" }, +] + +[[package]] +name = "yarl" +version = "1.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/63/0c6ebca57330cd313f6102b16dd57ffaf3ec4c83403dcb45dbd15c6f3ea1/yarl-1.22.0.tar.gz", hash = "sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71", size = 187169, upload-time = "2025-10-06T14:12:55.963Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/43/a2204825342f37c337f5edb6637040fa14e365b2fcc2346960201d457579/yarl-1.22.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c7bd6683587567e5a49ee6e336e0612bec8329be1b7d4c8af5687dcdeb67ee1e", size = 140517, upload-time = "2025-10-06T14:08:42.494Z" }, + { url = "https://files.pythonhosted.org/packages/44/6f/674f3e6f02266428c56f704cd2501c22f78e8b2eeb23f153117cc86fb28a/yarl-1.22.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5cdac20da754f3a723cceea5b3448e1a2074866406adeb4ef35b469d089adb8f", size = 93495, upload-time = "2025-10-06T14:08:46.2Z" }, + { url = "https://files.pythonhosted.org/packages/b8/12/5b274d8a0f30c07b91b2f02cba69152600b47830fcfb465c108880fcee9c/yarl-1.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07a524d84df0c10f41e3ee918846e1974aba4ec017f990dc735aad487a0bdfdf", size = 94400, upload-time = "2025-10-06T14:08:47.855Z" }, + { url = "https://files.pythonhosted.org/packages/e2/7f/df1b6949b1fa1aa9ff6de6e2631876ad4b73c4437822026e85d8acb56bb1/yarl-1.22.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1b329cb8146d7b736677a2440e422eadd775d1806a81db2d4cded80a48efc1a", size = 347545, upload-time = "2025-10-06T14:08:49.683Z" }, + { url = "https://files.pythonhosted.org/packages/84/09/f92ed93bd6cd77872ab6c3462df45ca45cd058d8f1d0c9b4f54c1704429f/yarl-1.22.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:75976c6945d85dbb9ee6308cd7ff7b1fb9409380c82d6119bd778d8fcfe2931c", size = 319598, upload-time = "2025-10-06T14:08:51.215Z" }, + { url = "https://files.pythonhosted.org/packages/c3/97/ac3f3feae7d522cf7ccec3d340bb0b2b61c56cb9767923df62a135092c6b/yarl-1.22.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:80ddf7a5f8c86cb3eb4bc9028b07bbbf1f08a96c5c0bc1244be5e8fefcb94147", size = 363893, upload-time = "2025-10-06T14:08:53.144Z" }, + { url = "https://files.pythonhosted.org/packages/06/49/f3219097403b9c84a4d079b1d7bda62dd9b86d0d6e4428c02d46ab2c77fc/yarl-1.22.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d332fc2e3c94dad927f2112395772a4e4fedbcf8f80efc21ed7cdfae4d574fdb", size = 371240, upload-time = "2025-10-06T14:08:55.036Z" }, + { url = "https://files.pythonhosted.org/packages/35/9f/06b765d45c0e44e8ecf0fe15c9eacbbde342bb5b7561c46944f107bfb6c3/yarl-1.22.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0cf71bf877efeac18b38d3930594c0948c82b64547c1cf420ba48722fe5509f6", size = 346965, upload-time = "2025-10-06T14:08:56.722Z" }, + { url = "https://files.pythonhosted.org/packages/c5/69/599e7cea8d0fcb1694323b0db0dda317fa3162f7b90166faddecf532166f/yarl-1.22.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:663e1cadaddae26be034a6ab6072449a8426ddb03d500f43daf952b74553bba0", size = 342026, upload-time = "2025-10-06T14:08:58.563Z" }, + { url = "https://files.pythonhosted.org/packages/95/6f/9dfd12c8bc90fea9eab39832ee32ea48f8e53d1256252a77b710c065c89f/yarl-1.22.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:6dcbb0829c671f305be48a7227918cfcd11276c2d637a8033a99a02b67bf9eda", size = 335637, upload-time = "2025-10-06T14:09:00.506Z" }, + { url = "https://files.pythonhosted.org/packages/57/2e/34c5b4eb9b07e16e873db5b182c71e5f06f9b5af388cdaa97736d79dd9a6/yarl-1.22.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f0d97c18dfd9a9af4490631905a3f131a8e4c9e80a39353919e2cfed8f00aedc", size = 359082, upload-time = "2025-10-06T14:09:01.936Z" }, + { url = "https://files.pythonhosted.org/packages/31/71/fa7e10fb772d273aa1f096ecb8ab8594117822f683bab7d2c5a89914c92a/yarl-1.22.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:437840083abe022c978470b942ff832c3940b2ad3734d424b7eaffcd07f76737", size = 357811, upload-time = "2025-10-06T14:09:03.445Z" }, + { url = "https://files.pythonhosted.org/packages/26/da/11374c04e8e1184a6a03cf9c8f5688d3e5cec83ed6f31ad3481b3207f709/yarl-1.22.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a899cbd98dce6f5d8de1aad31cb712ec0a530abc0a86bd6edaa47c1090138467", size = 351223, upload-time = "2025-10-06T14:09:05.401Z" }, + { url = "https://files.pythonhosted.org/packages/82/8f/e2d01f161b0c034a30410e375e191a5d27608c1f8693bab1a08b089ca096/yarl-1.22.0-cp310-cp310-win32.whl", hash = "sha256:595697f68bd1f0c1c159fcb97b661fc9c3f5db46498043555d04805430e79bea", size = 82118, upload-time = "2025-10-06T14:09:11.148Z" }, + { url = "https://files.pythonhosted.org/packages/62/46/94c76196642dbeae634c7a61ba3da88cd77bed875bf6e4a8bed037505aa6/yarl-1.22.0-cp310-cp310-win_amd64.whl", hash = "sha256:cb95a9b1adaa48e41815a55ae740cfda005758104049a640a398120bf02515ca", size = 86852, upload-time = "2025-10-06T14:09:12.958Z" }, + { url = "https://files.pythonhosted.org/packages/af/af/7df4f179d3b1a6dcb9a4bd2ffbc67642746fcafdb62580e66876ce83fff4/yarl-1.22.0-cp310-cp310-win_arm64.whl", hash = "sha256:b85b982afde6df99ecc996990d4ad7ccbdbb70e2a4ba4de0aecde5922ba98a0b", size = 82012, upload-time = "2025-10-06T14:09:14.664Z" }, + { url = "https://files.pythonhosted.org/packages/4d/27/5ab13fc84c76a0250afd3d26d5936349a35be56ce5785447d6c423b26d92/yarl-1.22.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ab72135b1f2db3fed3997d7e7dc1b80573c67138023852b6efb336a5eae6511", size = 141607, upload-time = "2025-10-06T14:09:16.298Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a1/d065d51d02dc02ce81501d476b9ed2229d9a990818332242a882d5d60340/yarl-1.22.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:669930400e375570189492dc8d8341301578e8493aec04aebc20d4717f899dd6", size = 94027, upload-time = "2025-10-06T14:09:17.786Z" }, + { url = "https://files.pythonhosted.org/packages/c1/da/8da9f6a53f67b5106ffe902c6fa0164e10398d4e150d85838b82f424072a/yarl-1.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:792a2af6d58177ef7c19cbf0097aba92ca1b9cb3ffdd9c7470e156c8f9b5e028", size = 94963, upload-time = "2025-10-06T14:09:19.662Z" }, + { url = "https://files.pythonhosted.org/packages/68/fe/2c1f674960c376e29cb0bec1249b117d11738db92a6ccc4a530b972648db/yarl-1.22.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ea66b1c11c9150f1372f69afb6b8116f2dd7286f38e14ea71a44eee9ec51b9d", size = 368406, upload-time = "2025-10-06T14:09:21.402Z" }, + { url = "https://files.pythonhosted.org/packages/95/26/812a540e1c3c6418fec60e9bbd38e871eaba9545e94fa5eff8f4a8e28e1e/yarl-1.22.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3e2daa88dc91870215961e96a039ec73e4937da13cf77ce17f9cad0c18df3503", size = 336581, upload-time = "2025-10-06T14:09:22.98Z" }, + { url = "https://files.pythonhosted.org/packages/0b/f5/5777b19e26fdf98563985e481f8be3d8a39f8734147a6ebf459d0dab5a6b/yarl-1.22.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba440ae430c00eee41509353628600212112cd5018d5def7e9b05ea7ac34eb65", size = 388924, upload-time = "2025-10-06T14:09:24.655Z" }, + { url = "https://files.pythonhosted.org/packages/86/08/24bd2477bd59c0bbd994fe1d93b126e0472e4e3df5a96a277b0a55309e89/yarl-1.22.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e6438cc8f23a9c1478633d216b16104a586b9761db62bfacb6425bac0a36679e", size = 392890, upload-time = "2025-10-06T14:09:26.617Z" }, + { url = "https://files.pythonhosted.org/packages/46/00/71b90ed48e895667ecfb1eaab27c1523ee2fa217433ed77a73b13205ca4b/yarl-1.22.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c52a6e78aef5cf47a98ef8e934755abf53953379b7d53e68b15ff4420e6683d", size = 365819, upload-time = "2025-10-06T14:09:28.544Z" }, + { url = "https://files.pythonhosted.org/packages/30/2d/f715501cae832651d3282387c6a9236cd26bd00d0ff1e404b3dc52447884/yarl-1.22.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3b06bcadaac49c70f4c88af4ffcfbe3dc155aab3163e75777818092478bcbbe7", size = 363601, upload-time = "2025-10-06T14:09:30.568Z" }, + { url = "https://files.pythonhosted.org/packages/f8/f9/a678c992d78e394e7126ee0b0e4e71bd2775e4334d00a9278c06a6cce96a/yarl-1.22.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6944b2dc72c4d7f7052683487e3677456050ff77fcf5e6204e98caf785ad1967", size = 358072, upload-time = "2025-10-06T14:09:32.528Z" }, + { url = "https://files.pythonhosted.org/packages/2c/d1/b49454411a60edb6fefdcad4f8e6dbba7d8019e3a508a1c5836cba6d0781/yarl-1.22.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d5372ca1df0f91a86b047d1277c2aaf1edb32d78bbcefffc81b40ffd18f027ed", size = 385311, upload-time = "2025-10-06T14:09:34.634Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/40d7a94debb8448c7771a916d1861d6609dddf7958dc381117e7ba36d9e8/yarl-1.22.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:51af598701f5299012b8416486b40fceef8c26fc87dc6d7d1f6fc30609ea0aa6", size = 381094, upload-time = "2025-10-06T14:09:36.268Z" }, + { url = "https://files.pythonhosted.org/packages/35/d8/611cc282502381ad855448643e1ad0538957fc82ae83dfe7762c14069e14/yarl-1.22.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b266bd01fedeffeeac01a79ae181719ff848a5a13ce10075adbefc8f1daee70e", size = 370944, upload-time = "2025-10-06T14:09:37.872Z" }, + { url = "https://files.pythonhosted.org/packages/2d/df/fadd00fb1c90e1a5a8bd731fa3d3de2e165e5a3666a095b04e31b04d9cb6/yarl-1.22.0-cp311-cp311-win32.whl", hash = "sha256:a9b1ba5610a4e20f655258d5a1fdc7ebe3d837bb0e45b581398b99eb98b1f5ca", size = 81804, upload-time = "2025-10-06T14:09:39.359Z" }, + { url = "https://files.pythonhosted.org/packages/b5/f7/149bb6f45f267cb5c074ac40c01c6b3ea6d8a620d34b337f6321928a1b4d/yarl-1.22.0-cp311-cp311-win_amd64.whl", hash = "sha256:078278b9b0b11568937d9509b589ee83ef98ed6d561dfe2020e24a9fd08eaa2b", size = 86858, upload-time = "2025-10-06T14:09:41.068Z" }, + { url = "https://files.pythonhosted.org/packages/2b/13/88b78b93ad3f2f0b78e13bfaaa24d11cbc746e93fe76d8c06bf139615646/yarl-1.22.0-cp311-cp311-win_arm64.whl", hash = "sha256:b6a6f620cfe13ccec221fa312139135166e47ae169f8253f72a0abc0dae94376", size = 81637, upload-time = "2025-10-06T14:09:42.712Z" }, + { url = "https://files.pythonhosted.org/packages/75/ff/46736024fee3429b80a165a732e38e5d5a238721e634ab41b040d49f8738/yarl-1.22.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e340382d1afa5d32b892b3ff062436d592ec3d692aeea3bef3a5cfe11bbf8c6f", size = 142000, upload-time = "2025-10-06T14:09:44.631Z" }, + { url = "https://files.pythonhosted.org/packages/5a/9a/b312ed670df903145598914770eb12de1bac44599549b3360acc96878df8/yarl-1.22.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f1e09112a2c31ffe8d80be1b0988fa6a18c5d5cad92a9ffbb1c04c91bfe52ad2", size = 94338, upload-time = "2025-10-06T14:09:46.372Z" }, + { url = "https://files.pythonhosted.org/packages/ba/f5/0601483296f09c3c65e303d60c070a5c19fcdbc72daa061e96170785bc7d/yarl-1.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:939fe60db294c786f6b7c2d2e121576628468f65453d86b0fe36cb52f987bd74", size = 94909, upload-time = "2025-10-06T14:09:48.648Z" }, + { url = "https://files.pythonhosted.org/packages/60/41/9a1fe0b73dbcefce72e46cf149b0e0a67612d60bfc90fb59c2b2efdfbd86/yarl-1.22.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e1651bf8e0398574646744c1885a41198eba53dc8a9312b954073f845c90a8df", size = 372940, upload-time = "2025-10-06T14:09:50.089Z" }, + { url = "https://files.pythonhosted.org/packages/17/7a/795cb6dfee561961c30b800f0ed616b923a2ec6258b5def2a00bf8231334/yarl-1.22.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b8a0588521a26bf92a57a1705b77b8b59044cdceccac7151bd8d229e66b8dedb", size = 345825, upload-time = "2025-10-06T14:09:52.142Z" }, + { url = "https://files.pythonhosted.org/packages/d7/93/a58f4d596d2be2ae7bab1a5846c4d270b894958845753b2c606d666744d3/yarl-1.22.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:42188e6a615c1a75bcaa6e150c3fe8f3e8680471a6b10150c5f7e83f47cc34d2", size = 386705, upload-time = "2025-10-06T14:09:54.128Z" }, + { url = "https://files.pythonhosted.org/packages/61/92/682279d0e099d0e14d7fd2e176bd04f48de1484f56546a3e1313cd6c8e7c/yarl-1.22.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f6d2cb59377d99718913ad9a151030d6f83ef420a2b8f521d94609ecc106ee82", size = 396518, upload-time = "2025-10-06T14:09:55.762Z" }, + { url = "https://files.pythonhosted.org/packages/db/0f/0d52c98b8a885aeda831224b78f3be7ec2e1aa4a62091f9f9188c3c65b56/yarl-1.22.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50678a3b71c751d58d7908edc96d332af328839eea883bb554a43f539101277a", size = 377267, upload-time = "2025-10-06T14:09:57.958Z" }, + { url = "https://files.pythonhosted.org/packages/22/42/d2685e35908cbeaa6532c1fc73e89e7f2efb5d8a7df3959ea8e37177c5a3/yarl-1.22.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e8fbaa7cec507aa24ea27a01456e8dd4b6fab829059b69844bd348f2d467124", size = 365797, upload-time = "2025-10-06T14:09:59.527Z" }, + { url = "https://files.pythonhosted.org/packages/a2/83/cf8c7bcc6355631762f7d8bdab920ad09b82efa6b722999dfb05afa6cfac/yarl-1.22.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:433885ab5431bc3d3d4f2f9bd15bfa1614c522b0f1405d62c4f926ccd69d04fa", size = 365535, upload-time = "2025-10-06T14:10:01.139Z" }, + { url = "https://files.pythonhosted.org/packages/25/e1/5302ff9b28f0c59cac913b91fe3f16c59a033887e57ce9ca5d41a3a94737/yarl-1.22.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b790b39c7e9a4192dc2e201a282109ed2985a1ddbd5ac08dc56d0e121400a8f7", size = 382324, upload-time = "2025-10-06T14:10:02.756Z" }, + { url = "https://files.pythonhosted.org/packages/bf/cd/4617eb60f032f19ae3a688dc990d8f0d89ee0ea378b61cac81ede3e52fae/yarl-1.22.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:31f0b53913220599446872d757257be5898019c85e7971599065bc55065dc99d", size = 383803, upload-time = "2025-10-06T14:10:04.552Z" }, + { url = "https://files.pythonhosted.org/packages/59/65/afc6e62bb506a319ea67b694551dab4a7e6fb7bf604e9bd9f3e11d575fec/yarl-1.22.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a49370e8f711daec68d09b821a34e1167792ee2d24d405cbc2387be4f158b520", size = 374220, upload-time = "2025-10-06T14:10:06.489Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3d/68bf18d50dc674b942daec86a9ba922d3113d8399b0e52b9897530442da2/yarl-1.22.0-cp312-cp312-win32.whl", hash = "sha256:70dfd4f241c04bd9239d53b17f11e6ab672b9f1420364af63e8531198e3f5fe8", size = 81589, upload-time = "2025-10-06T14:10:09.254Z" }, + { url = "https://files.pythonhosted.org/packages/c8/9a/6ad1a9b37c2f72874f93e691b2e7ecb6137fb2b899983125db4204e47575/yarl-1.22.0-cp312-cp312-win_amd64.whl", hash = "sha256:8884d8b332a5e9b88e23f60bb166890009429391864c685e17bd73a9eda9105c", size = 87213, upload-time = "2025-10-06T14:10:11.369Z" }, + { url = "https://files.pythonhosted.org/packages/44/c5/c21b562d1680a77634d748e30c653c3ca918beb35555cff24986fff54598/yarl-1.22.0-cp312-cp312-win_arm64.whl", hash = "sha256:ea70f61a47f3cc93bdf8b2f368ed359ef02a01ca6393916bc8ff877427181e74", size = 81330, upload-time = "2025-10-06T14:10:13.112Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f3/d67de7260456ee105dc1d162d43a019ecad6b91e2f51809d6cddaa56690e/yarl-1.22.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8dee9c25c74997f6a750cd317b8ca63545169c098faee42c84aa5e506c819b53", size = 139980, upload-time = "2025-10-06T14:10:14.601Z" }, + { url = "https://files.pythonhosted.org/packages/01/88/04d98af0b47e0ef42597b9b28863b9060bb515524da0a65d5f4db160b2d5/yarl-1.22.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01e73b85a5434f89fc4fe27dcda2aff08ddf35e4d47bbbea3bdcd25321af538a", size = 93424, upload-time = "2025-10-06T14:10:16.115Z" }, + { url = "https://files.pythonhosted.org/packages/18/91/3274b215fd8442a03975ce6bee5fe6aa57a8326b29b9d3d56234a1dca244/yarl-1.22.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22965c2af250d20c873cdbee8ff958fb809940aeb2e74ba5f20aaf6b7ac8c70c", size = 93821, upload-time = "2025-10-06T14:10:17.993Z" }, + { url = "https://files.pythonhosted.org/packages/61/3a/caf4e25036db0f2da4ca22a353dfeb3c9d3c95d2761ebe9b14df8fc16eb0/yarl-1.22.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4f15793aa49793ec8d1c708ab7f9eded1aa72edc5174cae703651555ed1b601", size = 373243, upload-time = "2025-10-06T14:10:19.44Z" }, + { url = "https://files.pythonhosted.org/packages/6e/9e/51a77ac7516e8e7803b06e01f74e78649c24ee1021eca3d6a739cb6ea49c/yarl-1.22.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5542339dcf2747135c5c85f68680353d5cb9ffd741c0f2e8d832d054d41f35a", size = 342361, upload-time = "2025-10-06T14:10:21.124Z" }, + { url = "https://files.pythonhosted.org/packages/d4/f8/33b92454789dde8407f156c00303e9a891f1f51a0330b0fad7c909f87692/yarl-1.22.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5c401e05ad47a75869c3ab3e35137f8468b846770587e70d71e11de797d113df", size = 387036, upload-time = "2025-10-06T14:10:22.902Z" }, + { url = "https://files.pythonhosted.org/packages/d9/9a/c5db84ea024f76838220280f732970aa4ee154015d7f5c1bfb60a267af6f/yarl-1.22.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:243dda95d901c733f5b59214d28b0120893d91777cb8aa043e6ef059d3cddfe2", size = 397671, upload-time = "2025-10-06T14:10:24.523Z" }, + { url = "https://files.pythonhosted.org/packages/11/c9/cd8538dc2e7727095e0c1d867bad1e40c98f37763e6d995c1939f5fdc7b1/yarl-1.22.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bec03d0d388060058f5d291a813f21c011041938a441c593374da6077fe21b1b", size = 377059, upload-time = "2025-10-06T14:10:26.406Z" }, + { url = "https://files.pythonhosted.org/packages/a1/b9/ab437b261702ced75122ed78a876a6dec0a1b0f5e17a4ac7a9a2482d8abe/yarl-1.22.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0748275abb8c1e1e09301ee3cf90c8a99678a4e92e4373705f2a2570d581273", size = 365356, upload-time = "2025-10-06T14:10:28.461Z" }, + { url = "https://files.pythonhosted.org/packages/b2/9d/8e1ae6d1d008a9567877b08f0ce4077a29974c04c062dabdb923ed98e6fe/yarl-1.22.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:47fdb18187e2a4e18fda2c25c05d8251a9e4a521edaed757fef033e7d8498d9a", size = 361331, upload-time = "2025-10-06T14:10:30.541Z" }, + { url = "https://files.pythonhosted.org/packages/ca/5a/09b7be3905962f145b73beb468cdd53db8aa171cf18c80400a54c5b82846/yarl-1.22.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c7044802eec4524fde550afc28edda0dd5784c4c45f0be151a2d3ba017daca7d", size = 382590, upload-time = "2025-10-06T14:10:33.352Z" }, + { url = "https://files.pythonhosted.org/packages/aa/7f/59ec509abf90eda5048b0bc3e2d7b5099dffdb3e6b127019895ab9d5ef44/yarl-1.22.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:139718f35149ff544caba20fce6e8a2f71f1e39b92c700d8438a0b1d2a631a02", size = 385316, upload-time = "2025-10-06T14:10:35.034Z" }, + { url = "https://files.pythonhosted.org/packages/e5/84/891158426bc8036bfdfd862fabd0e0fa25df4176ec793e447f4b85cf1be4/yarl-1.22.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1b51bebd221006d3d2f95fbe124b22b247136647ae5dcc8c7acafba66e5ee67", size = 374431, upload-time = "2025-10-06T14:10:37.76Z" }, + { url = "https://files.pythonhosted.org/packages/bb/49/03da1580665baa8bef5e8ed34c6df2c2aca0a2f28bf397ed238cc1bbc6f2/yarl-1.22.0-cp313-cp313-win32.whl", hash = "sha256:d3e32536234a95f513bd374e93d717cf6b2231a791758de6c509e3653f234c95", size = 81555, upload-time = "2025-10-06T14:10:39.649Z" }, + { url = "https://files.pythonhosted.org/packages/9a/ee/450914ae11b419eadd067c6183ae08381cfdfcb9798b90b2b713bbebddda/yarl-1.22.0-cp313-cp313-win_amd64.whl", hash = "sha256:47743b82b76d89a1d20b83e60d5c20314cbd5ba2befc9cda8f28300c4a08ed4d", size = 86965, upload-time = "2025-10-06T14:10:41.313Z" }, + { url = "https://files.pythonhosted.org/packages/98/4d/264a01eae03b6cf629ad69bae94e3b0e5344741e929073678e84bf7a3e3b/yarl-1.22.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d0fcda9608875f7d052eff120c7a5da474a6796fe4d83e152e0e4d42f6d1a9b", size = 81205, upload-time = "2025-10-06T14:10:43.167Z" }, + { url = "https://files.pythonhosted.org/packages/88/fc/6908f062a2f77b5f9f6d69cecb1747260831ff206adcbc5b510aff88df91/yarl-1.22.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:719ae08b6972befcba4310e49edb1161a88cdd331e3a694b84466bd938a6ab10", size = 146209, upload-time = "2025-10-06T14:10:44.643Z" }, + { url = "https://files.pythonhosted.org/packages/65/47/76594ae8eab26210b4867be6f49129861ad33da1f1ebdf7051e98492bf62/yarl-1.22.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:47d8a5c446df1c4db9d21b49619ffdba90e77c89ec6e283f453856c74b50b9e3", size = 95966, upload-time = "2025-10-06T14:10:46.554Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ce/05e9828a49271ba6b5b038b15b3934e996980dd78abdfeb52a04cfb9467e/yarl-1.22.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cfebc0ac8333520d2d0423cbbe43ae43c8838862ddb898f5ca68565e395516e9", size = 97312, upload-time = "2025-10-06T14:10:48.007Z" }, + { url = "https://files.pythonhosted.org/packages/d1/c5/7dffad5e4f2265b29c9d7ec869c369e4223166e4f9206fc2243ee9eea727/yarl-1.22.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4398557cbf484207df000309235979c79c4356518fd5c99158c7d38203c4da4f", size = 361967, upload-time = "2025-10-06T14:10:49.997Z" }, + { url = "https://files.pythonhosted.org/packages/50/b2/375b933c93a54bff7fc041e1a6ad2c0f6f733ffb0c6e642ce56ee3b39970/yarl-1.22.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2ca6fd72a8cd803be290d42f2dec5cdcd5299eeb93c2d929bf060ad9efaf5de0", size = 323949, upload-time = "2025-10-06T14:10:52.004Z" }, + { url = "https://files.pythonhosted.org/packages/66/50/bfc2a29a1d78644c5a7220ce2f304f38248dc94124a326794e677634b6cf/yarl-1.22.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca1f59c4e1ab6e72f0a23c13fca5430f889634166be85dbf1013683e49e3278e", size = 361818, upload-time = "2025-10-06T14:10:54.078Z" }, + { url = "https://files.pythonhosted.org/packages/46/96/f3941a46af7d5d0f0498f86d71275696800ddcdd20426298e572b19b91ff/yarl-1.22.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c5010a52015e7c70f86eb967db0f37f3c8bd503a695a49f8d45700144667708", size = 372626, upload-time = "2025-10-06T14:10:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/c1/42/8b27c83bb875cd89448e42cd627e0fb971fa1675c9ec546393d18826cb50/yarl-1.22.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d7672ecf7557476642c88497c2f8d8542f8e36596e928e9bcba0e42e1e7d71f", size = 341129, upload-time = "2025-10-06T14:10:57.985Z" }, + { url = "https://files.pythonhosted.org/packages/49/36/99ca3122201b382a3cf7cc937b95235b0ac944f7e9f2d5331d50821ed352/yarl-1.22.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3b7c88eeef021579d600e50363e0b6ee4f7f6f728cd3486b9d0f3ee7b946398d", size = 346776, upload-time = "2025-10-06T14:10:59.633Z" }, + { url = "https://files.pythonhosted.org/packages/85/b4/47328bf996acd01a4c16ef9dcd2f59c969f495073616586f78cd5f2efb99/yarl-1.22.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f4afb5c34f2c6fecdcc182dfcfc6af6cccf1aa923eed4d6a12e9d96904e1a0d8", size = 334879, upload-time = "2025-10-06T14:11:01.454Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ad/b77d7b3f14a4283bffb8e92c6026496f6de49751c2f97d4352242bba3990/yarl-1.22.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:59c189e3e99a59cf8d83cbb31d4db02d66cda5a1a4374e8a012b51255341abf5", size = 350996, upload-time = "2025-10-06T14:11:03.452Z" }, + { url = "https://files.pythonhosted.org/packages/81/c8/06e1d69295792ba54d556f06686cbd6a7ce39c22307100e3fb4a2c0b0a1d/yarl-1.22.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:5a3bf7f62a289fa90f1990422dc8dff5a458469ea71d1624585ec3a4c8d6960f", size = 356047, upload-time = "2025-10-06T14:11:05.115Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b8/4c0e9e9f597074b208d18cef227d83aac36184bfbc6eab204ea55783dbc5/yarl-1.22.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:de6b9a04c606978fdfe72666fa216ffcf2d1a9f6a381058d4378f8d7b1e5de62", size = 342947, upload-time = "2025-10-06T14:11:08.137Z" }, + { url = "https://files.pythonhosted.org/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03", size = 86943, upload-time = "2025-10-06T14:11:10.284Z" }, + { url = "https://files.pythonhosted.org/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249", size = 93715, upload-time = "2025-10-06T14:11:11.739Z" }, + { url = "https://files.pythonhosted.org/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b", size = 83857, upload-time = "2025-10-06T14:11:13.586Z" }, + { url = "https://files.pythonhosted.org/packages/46/b3/e20ef504049f1a1c54a814b4b9bed96d1ac0e0610c3b4da178f87209db05/yarl-1.22.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4", size = 140520, upload-time = "2025-10-06T14:11:15.465Z" }, + { url = "https://files.pythonhosted.org/packages/e4/04/3532d990fdbab02e5ede063676b5c4260e7f3abea2151099c2aa745acc4c/yarl-1.22.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683", size = 93504, upload-time = "2025-10-06T14:11:17.106Z" }, + { url = "https://files.pythonhosted.org/packages/11/63/ff458113c5c2dac9a9719ac68ee7c947cb621432bcf28c9972b1c0e83938/yarl-1.22.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b", size = 94282, upload-time = "2025-10-06T14:11:19.064Z" }, + { url = "https://files.pythonhosted.org/packages/a7/bc/315a56aca762d44a6aaaf7ad253f04d996cb6b27bad34410f82d76ea8038/yarl-1.22.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e", size = 372080, upload-time = "2025-10-06T14:11:20.996Z" }, + { url = "https://files.pythonhosted.org/packages/3f/3f/08e9b826ec2e099ea6e7c69a61272f4f6da62cb5b1b63590bb80ca2e4a40/yarl-1.22.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590", size = 338696, upload-time = "2025-10-06T14:11:22.847Z" }, + { url = "https://files.pythonhosted.org/packages/e3/9f/90360108e3b32bd76789088e99538febfea24a102380ae73827f62073543/yarl-1.22.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2", size = 387121, upload-time = "2025-10-06T14:11:24.889Z" }, + { url = "https://files.pythonhosted.org/packages/98/92/ab8d4657bd5b46a38094cfaea498f18bb70ce6b63508fd7e909bd1f93066/yarl-1.22.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da", size = 394080, upload-time = "2025-10-06T14:11:27.307Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e7/d8c5a7752fef68205296201f8ec2bf718f5c805a7a7e9880576c67600658/yarl-1.22.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784", size = 372661, upload-time = "2025-10-06T14:11:29.387Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2e/f4d26183c8db0bb82d491b072f3127fb8c381a6206a3a56332714b79b751/yarl-1.22.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b", size = 364645, upload-time = "2025-10-06T14:11:31.423Z" }, + { url = "https://files.pythonhosted.org/packages/80/7c/428e5812e6b87cd00ee8e898328a62c95825bf37c7fa87f0b6bb2ad31304/yarl-1.22.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694", size = 355361, upload-time = "2025-10-06T14:11:33.055Z" }, + { url = "https://files.pythonhosted.org/packages/ec/2a/249405fd26776f8b13c067378ef4d7dd49c9098d1b6457cdd152a99e96a9/yarl-1.22.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d", size = 381451, upload-time = "2025-10-06T14:11:35.136Z" }, + { url = "https://files.pythonhosted.org/packages/67/a8/fb6b1adbe98cf1e2dd9fad71003d3a63a1bc22459c6e15f5714eb9323b93/yarl-1.22.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd", size = 383814, upload-time = "2025-10-06T14:11:37.094Z" }, + { url = "https://files.pythonhosted.org/packages/d9/f9/3aa2c0e480fb73e872ae2814c43bc1e734740bb0d54e8cb2a95925f98131/yarl-1.22.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da", size = 370799, upload-time = "2025-10-06T14:11:38.83Z" }, + { url = "https://files.pythonhosted.org/packages/50/3c/af9dba3b8b5eeb302f36f16f92791f3ea62e3f47763406abf6d5a4a3333b/yarl-1.22.0-cp314-cp314-win32.whl", hash = "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2", size = 82990, upload-time = "2025-10-06T14:11:40.624Z" }, + { url = "https://files.pythonhosted.org/packages/ac/30/ac3a0c5bdc1d6efd1b41fa24d4897a4329b3b1e98de9449679dd327af4f0/yarl-1.22.0-cp314-cp314-win_amd64.whl", hash = "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79", size = 88292, upload-time = "2025-10-06T14:11:42.578Z" }, + { url = "https://files.pythonhosted.org/packages/df/0a/227ab4ff5b998a1b7410abc7b46c9b7a26b0ca9e86c34ba4b8d8bc7c63d5/yarl-1.22.0-cp314-cp314-win_arm64.whl", hash = "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33", size = 82888, upload-time = "2025-10-06T14:11:44.863Z" }, + { url = "https://files.pythonhosted.org/packages/06/5e/a15eb13db90abd87dfbefb9760c0f3f257ac42a5cac7e75dbc23bed97a9f/yarl-1.22.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1", size = 146223, upload-time = "2025-10-06T14:11:46.796Z" }, + { url = "https://files.pythonhosted.org/packages/18/82/9665c61910d4d84f41a5bf6837597c89e665fa88aa4941080704645932a9/yarl-1.22.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca", size = 95981, upload-time = "2025-10-06T14:11:48.845Z" }, + { url = "https://files.pythonhosted.org/packages/5d/9a/2f65743589809af4d0a6d3aa749343c4b5f4c380cc24a8e94a3c6625a808/yarl-1.22.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53", size = 97303, upload-time = "2025-10-06T14:11:50.897Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ab/5b13d3e157505c43c3b43b5a776cbf7b24a02bc4cccc40314771197e3508/yarl-1.22.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c", size = 361820, upload-time = "2025-10-06T14:11:52.549Z" }, + { url = "https://files.pythonhosted.org/packages/fb/76/242a5ef4677615cf95330cfc1b4610e78184400699bdda0acb897ef5e49a/yarl-1.22.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf", size = 323203, upload-time = "2025-10-06T14:11:54.225Z" }, + { url = "https://files.pythonhosted.org/packages/8c/96/475509110d3f0153b43d06164cf4195c64d16999e0c7e2d8a099adcd6907/yarl-1.22.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face", size = 363173, upload-time = "2025-10-06T14:11:56.069Z" }, + { url = "https://files.pythonhosted.org/packages/c9/66/59db471aecfbd559a1fd48aedd954435558cd98c7d0da8b03cc6c140a32c/yarl-1.22.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b", size = 373562, upload-time = "2025-10-06T14:11:58.783Z" }, + { url = "https://files.pythonhosted.org/packages/03/1f/c5d94abc91557384719da10ff166b916107c1b45e4d0423a88457071dd88/yarl-1.22.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486", size = 339828, upload-time = "2025-10-06T14:12:00.686Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/aa6a143d3afba17b6465733681c70cf175af89f76ec8d9286e08437a7454/yarl-1.22.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138", size = 347551, upload-time = "2025-10-06T14:12:02.628Z" }, + { url = "https://files.pythonhosted.org/packages/43/3c/45a2b6d80195959239a7b2a8810506d4eea5487dce61c2a3393e7fc3c52e/yarl-1.22.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a", size = 334512, upload-time = "2025-10-06T14:12:04.871Z" }, + { url = "https://files.pythonhosted.org/packages/86/a0/c2ab48d74599c7c84cb104ebd799c5813de252bea0f360ffc29d270c2caa/yarl-1.22.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529", size = 352400, upload-time = "2025-10-06T14:12:06.624Z" }, + { url = "https://files.pythonhosted.org/packages/32/75/f8919b2eafc929567d3d8411f72bdb1a2109c01caaab4ebfa5f8ffadc15b/yarl-1.22.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093", size = 357140, upload-time = "2025-10-06T14:12:08.362Z" }, + { url = "https://files.pythonhosted.org/packages/cf/72/6a85bba382f22cf78add705d8c3731748397d986e197e53ecc7835e76de7/yarl-1.22.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c", size = 341473, upload-time = "2025-10-06T14:12:10.994Z" }, + { url = "https://files.pythonhosted.org/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e", size = 89056, upload-time = "2025-10-06T14:12:13.317Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27", size = 96292, upload-time = "2025-10-06T14:12:15.398Z" }, + { url = "https://files.pythonhosted.org/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1", size = 85171, upload-time = "2025-10-06T14:12:16.935Z" }, + { url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" }, +]