{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "eda20efe-ad2b-4bcc-be64-bfcff1e7f820", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== Building benchmark pool ===\n", " Loading benchmark: benchmark15.csv\n", " Loading benchmark: benchmark16.csv\n", " Loading benchmark: benchmark20.csv\n", " Loading benchmark: benchmark19.csv\n", " → Benchmark pool size: 521 unique normalized strings\n", "\n", "=== Checking training files ===\n", " Checking: a_p_n_ss.csv\n", " → 0 contaminated rows removed. Cleaned saved to: output/cleaned/a_p_n_ss.csv\n", " Checking: a_p_n_sts.csv\n", " → 637 contaminated rows removed. Cleaned saved to: output/cleaned/a_p_n_sts.csv\n", " Checking: a_p_ss.csv\n", " → 0 contaminated rows removed. Cleaned saved to: output/cleaned/a_p_ss.csv\n", " Checking: MultiNeg_4_ss.csv\n", " → 0 contaminated rows removed. Cleaned saved to: output/cleaned/MultiNeg_4_ss.csv\n", " Checking: MultiNeg_30_ss.csv\n", " → 0 contaminated rows removed. Cleaned saved to: output/cleaned/MultiNeg_30_ss.csv\n", " Checking: s1_s2_label_ss.csv\n", " → 0 contaminated rows removed. Cleaned saved to: output/cleaned/s1_s2_label_ss.csv\n", " Checking: s1_s2_label_sts.csv\n", " → 0 contaminated rows removed. Cleaned saved to: output/cleaned/s1_s2_label_sts.csv\n", " Checking: s1_s2_score_sts.csv\n", " → 3358 contaminated rows removed. Cleaned saved to: output/cleaned/s1_s2_score_sts.csv\n", "\n", "=== Done ===\n", " Detailed report : output/contamination_report.csv\n", " Summary report : output/summary_report.csv\n", " Cleaned CSVs : output/cleaned/\n", "\n", "── Summary ──────────────────────────────────────\n", " training_file original_rows contaminated_rows cleaned_rows contaminated_cells\n", " a_p_n_ss.csv 3538680 0 3538680 0\n", " a_p_n_sts.csv 5628452 637 5627815 637\n", " a_p_ss.csv 277638 0 277638 0\n", " MultiNeg_4_ss.csv 500 0 500 0\n", " MultiNeg_30_ss.csv 3839 0 3839 0\n", " s1_s2_label_ss.csv 436 0 436 0\n", "s1_s2_label_sts.csv 15712 0 15712 0\n", "s1_s2_score_sts.csv 11340 3358 7982 3358\n", "\n", "Total contaminated rows across all files: 3,995\n" ] } ], "source": [ "\"\"\"\n", "Contamination Checker\n", "=====================\n", "Checks whether any text from benchmark datasets appears in training CSVs.\n", "\n", "Matching strategy: exact match after normalization\n", " - lowercase\n", " - strip leading/trailing whitespace\n", " - collapse internal spaces\n", " - strip Arabic diacritics (tashkeel)\n", "\n", "Usage\n", "-----\n", "1. Set BENCHMARK_FILES and TRAINING_FILES at the bottom of this script.\n", "2. Run: python check_contamination.py\n", "3. Outputs:\n", " - contamination_report.csv → every hit with full provenance\n", " - summary_report.csv → per-file contamination counts\n", " - cleaned/ → training CSVs with contaminated rows removed\n", "\"\"\"\n", "\n", "import os\n", "import re\n", "import unicodedata\n", "import pandas as pd\n", "from pathlib import Path\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 1. NORMALIZATION\n", "# ─────────────────────────────────────────────\n", "\n", "# Arabic diacritics Unicode range (tashkeel, harakat, shadda, tanween, etc.)\n", "ARABIC_DIACRITICS = re.compile(r'[\\u0610-\\u061A\\u064B-\\u065F\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED]')\n", "\n", "def normalize(text: str) -> str:\n", " \"\"\"Normalize a string for comparison.\"\"\"\n", " if not isinstance(text, str):\n", " return \"\"\n", " text = ARABIC_DIACRITICS.sub(\"\", text) # strip Arabic diacritics\n", " text = text.lower() # lowercase\n", " text = \" \".join(text.split()) # collapse whitespace\n", " return text.strip()\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 2. FLATTEN A DATAFRAME → SET OF STRINGS\n", "# ─────────────────────────────────────────────\n", "\n", "def flatten_df(df: pd.DataFrame) -> set[str]:\n", " \"\"\"Extract all non-empty normalized strings from every cell in a DataFrame.\"\"\"\n", " strings = set()\n", " for col in df.columns:\n", " for val in df[col].dropna():\n", " normed = normalize(str(val))\n", " if normed:\n", " strings.add(normed)\n", " return strings\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 3. LOAD BENCHMARK FILES → MASTER SET\n", "# ─────────────────────────────────────────────\n", "\n", "def build_benchmark_pool(benchmark_files: list[str]) -> set[str]:\n", " \"\"\"\n", " Load all benchmark CSVs and return one master set of normalized strings.\n", " Handles special cases per dataset if needed (e.g. filtering ar-ar rows).\n", " \"\"\"\n", " pool = set()\n", " for path in benchmark_files:\n", " print(f\" Loading benchmark: {path}\")\n", " df = pd.read_csv(path, low_memory=False)\n", " pool |= flatten_df(df)\n", " print(f\" → Benchmark pool size: {len(pool):,} unique normalized strings\\n\")\n", " return pool\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 4. CHECK ONE TRAINING FILE\n", "# ─────────────────────────────────────────────\n", "\n", "def check_training_file(\n", " path: str,\n", " benchmark_pool: set[str]\n", ") -> tuple[pd.DataFrame, list[dict]]:\n", " \"\"\"\n", " Check a training CSV for contamination.\n", "\n", " Returns\n", " -------\n", " clean_df : DataFrame with contaminated rows removed\n", " hits : list of dicts describing every contaminated cell found\n", " \"\"\"\n", " df = pd.read_csv(path, low_memory=False)\n", " filename = Path(path).name\n", "\n", " contaminated_row_indices = set()\n", " hits = []\n", "\n", " for col in df.columns:\n", " for idx, val in df[col].dropna().items():\n", " normed = normalize(str(val))\n", " if normed and normed in benchmark_pool:\n", " contaminated_row_indices.add(idx)\n", " hits.append({\n", " \"training_file\": filename,\n", " \"row_index\": idx,\n", " \"column\": col,\n", " \"original_value\": str(val),\n", " \"normalized_value\": normed,\n", " })\n", "\n", " clean_df = df.drop(index=list(contaminated_row_indices)).reset_index(drop=True)\n", " return clean_df, hits\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 5. MAIN\n", "# ─────────────────────────────────────────────\n", "\n", "def run(\n", " benchmark_files: list[str],\n", " training_files: list[str],\n", " output_dir: str = \".\",\n", "):\n", " cleaned_dir = Path(output_dir) / \"cleaned\"\n", " cleaned_dir.mkdir(parents=True, exist_ok=True)\n", "\n", " # ── Build benchmark pool ──────────────────\n", " print(\"=== Building benchmark pool ===\")\n", " benchmark_pool = build_benchmark_pool(benchmark_files)\n", "\n", " # ── Check each training file ──────────────\n", " all_hits = []\n", " summary_rows = []\n", "\n", " print(\"=== Checking training files ===\")\n", " for path in training_files:\n", " filename = Path(path).name\n", " print(f\" Checking: {filename}\")\n", "\n", " clean_df, hits = check_training_file(path, benchmark_pool)\n", "\n", " contaminated_rows = len(set(h[\"row_index\"] for h in hits))\n", " original_rows = len(pd.read_csv(path, low_memory=False))\n", " kept_rows = len(clean_df)\n", "\n", " summary_rows.append({\n", " \"training_file\": filename,\n", " \"original_rows\": original_rows,\n", " \"contaminated_rows\": contaminated_rows,\n", " \"cleaned_rows\": kept_rows,\n", " \"contaminated_cells\": len(hits),\n", " })\n", "\n", " all_hits.extend(hits)\n", "\n", " # Save cleaned CSV\n", " out_path = cleaned_dir / filename\n", " clean_df.to_csv(out_path, index=False)\n", " print(f\" → {contaminated_rows} contaminated rows removed. Cleaned saved to: {out_path}\")\n", "\n", " # ── Save reports ──────────────────────────\n", " report_path = Path(output_dir) / \"contamination_report.csv\"\n", " summary_path = Path(output_dir) / \"summary_report.csv\"\n", "\n", " pd.DataFrame(all_hits).to_csv(report_path, index=False)\n", " pd.DataFrame(summary_rows).to_csv(summary_path, index=False)\n", "\n", " print(\"\\n=== Done ===\")\n", " print(f\" Detailed report : {report_path}\")\n", " print(f\" Summary report : {summary_path}\")\n", " print(f\" Cleaned CSVs : {cleaned_dir}/\")\n", "\n", " # ── Print summary to console ──────────────\n", " print(\"\\n── Summary ──────────────────────────────────────\")\n", " summary_df = pd.DataFrame(summary_rows)\n", " print(summary_df.to_string(index=False))\n", " total_contaminated = summary_df[\"contaminated_rows\"].sum()\n", " print(f\"\\nTotal contaminated rows across all files: {total_contaminated:,}\")\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 6. CONFIGURE AND RUN\n", "# ─────────────────────────────────────────────\n", "\n", "if __name__ == \"__main__\":\n", "\n", " # ── Benchmark CSVs (pre-downloaded from HuggingFace) ──\n", " # For mteb/sts22 and mteb/sts17, if your CSV has rows for multiple\n", " # languages, filter to Arabic rows BEFORE passing here, or name\n", " # your pre-filtered files accordingly (e.g. sts22_ar.csv).\n", " BENCHMARK_FILES = [\n", " \"benchmark15.csv\", # Ruqiya/Arabic-stsbenchmark-sts-ar\n", " \"benchmark16.csv\", # LLMXperts/Arabic-stsb\n", " \"benchmark20.csv\", # mteb/sts22-crosslingual-sts (ar rows only)\n", " \"benchmark19.csv\", # mteb/sts17-crosslingual-sts (ar-ar rows only)\n", " ]\n", "\n", " # ── Your 8 training CSVs ──\n", " TRAINING_FILES = [\n", " \"a_p_n_ss.csv\",\n", " \"a_p_n_sts.csv\",\n", " \"a_p_ss.csv\",\n", " \"MultiNeg_4_ss.csv\",\n", " \"MultiNeg_30_ss.csv\",\n", " \"s1_s2_label_ss.csv\",\n", " \"s1_s2_label_sts.csv\",\n", " \"s1_s2_score_sts.csv\"\n", " ]\n", "\n", " # ── Output directory ──\n", " OUTPUT_DIR = \"reports\"\n", "\n", " run(BENCHMARK_FILES, TRAINING_FILES, OUTPUT_DIR)" ] }, { "cell_type": "code", "execution_count": 2, "id": "2671c5b3-dee3-4010-9ea9-4ea774acb36d", "metadata": {}, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 7, "id": "2570a5df-5654-49ee-a6de-6c119f7fb45e", "metadata": {}, "outputs": [], "source": [ "df=pd.read_csv('output/summary_report.csv')" ] }, { "cell_type": "code", "execution_count": 6, "id": "f0c08380-4fb3-473a-87f7-b56ad673fe7e", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
training_fileoriginal_rowscontaminated_rowscleaned_rowscontaminated_cells
0a_p_n_ss.csv3538680035386800
1a_p_n_sts.csv56284526375627815637
2a_p_ss.csv27763802776380
3MultiNeg_4_ss.csv50005000
4MultiNeg_30_ss.csv3839038390
5s1_s2_label_ss.csv43604360
6s1_s2_label_sts.csv157120157120
7s1_s2_score_sts.csv11340335879823358
\n", "
" ], "text/plain": [ " training_file original_rows contaminated_rows cleaned_rows \\\n", "0 a_p_n_ss.csv 3538680 0 3538680 \n", "1 a_p_n_sts.csv 5628452 637 5627815 \n", "2 a_p_ss.csv 277638 0 277638 \n", "3 MultiNeg_4_ss.csv 500 0 500 \n", "4 MultiNeg_30_ss.csv 3839 0 3839 \n", "5 s1_s2_label_ss.csv 436 0 436 \n", "6 s1_s2_label_sts.csv 15712 0 15712 \n", "7 s1_s2_score_sts.csv 11340 3358 7982 \n", "\n", " contaminated_cells \n", "0 0 \n", "1 637 \n", "2 0 \n", "3 0 \n", "4 0 \n", "5 0 \n", "6 0 \n", "7 3358 " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df" ] }, { "cell_type": "code", "execution_count": 12, "id": "cfa3fda8-c2ab-49a8-a8be-8b4556dc5311", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "=== Building benchmark pool ===\n", " Loading benchmark: ./benchmark/benchmark15.csv\n", " Loading benchmark: ./benchmark/benchmark16.csv\n", " Loading benchmark: ./benchmark/benchmark20.csv\n", " Loading benchmark: ./benchmark/benchmark19.csv\n", " → Benchmark pool size: 521 unique normalized strings\n", "\n", "=== Checking training files ===\n", " Checking: clean_dataset36_val.csv\n", " → 0 contaminated rows removed. Cleaned saved to: reports/cleaned/clean_dataset36_val.csv\n", " Checking: clean_dataset36_train.csv\n", " → 0 contaminated rows removed. Cleaned saved to: reports/cleaned/clean_dataset36_train.csv\n", "\n", "=== Done ===\n", " Detailed report : reports/contamination_report.csv\n", " Summary report : reports/summary_report.csv\n", " Cleaned CSVs : reports/cleaned/\n", "\n", "── Summary ──────────────────────────────────────\n", " training_file original_rows contaminated_rows cleaned_rows contaminated_cells\n", " clean_dataset36_val.csv 10000 0 10000 0\n", "clean_dataset36_train.csv 18596913 0 18596913 0\n", "\n", "Total contaminated rows across all files: 0\n" ] } ], "source": [ "\"\"\"\n", "Contamination Checker\n", "=====================\n", "Checks whether any text from benchmark datasets appears in training CSVs.\n", "\n", "Matching strategy: exact match after normalization\n", " - lowercase\n", " - strip leading/trailing whitespace\n", " - collapse internal spaces\n", " - strip Arabic diacritics (tashkeel)\n", "\n", "Usage\n", "-----\n", "1. Set BENCHMARK_FILES and TRAINING_FILES at the bottom of this script.\n", "2. Run: python check_contamination.py\n", "3. Outputs:\n", " - contamination_report.csv → every hit with full provenance\n", " - summary_report.csv → per-file contamination counts\n", " - cleaned/ → training CSVs with contaminated rows removed\n", "\"\"\"\n", "\n", "import os\n", "import re\n", "import unicodedata\n", "import pandas as pd\n", "from pathlib import Path\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 1. NORMALIZATION\n", "# ─────────────────────────────────────────────\n", "\n", "# Arabic diacritics Unicode range (tashkeel, harakat, shadda, tanween, etc.)\n", "ARABIC_DIACRITICS = re.compile(r'[\\u0610-\\u061A\\u064B-\\u065F\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED]')\n", "\n", "def normalize(text: str) -> str:\n", " \"\"\"Normalize a string for comparison.\"\"\"\n", " if not isinstance(text, str):\n", " return \"\"\n", " text = ARABIC_DIACRITICS.sub(\"\", text) # strip Arabic diacritics\n", " text = text.lower() # lowercase\n", " text = \" \".join(text.split()) # collapse whitespace\n", " return text.strip()\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 2. FLATTEN A DATAFRAME → SET OF STRINGS\n", "# ─────────────────────────────────────────────\n", "\n", "def flatten_df(df: pd.DataFrame) -> set[str]:\n", " \"\"\"Extract all non-empty normalized strings from every cell in a DataFrame.\"\"\"\n", " strings = set()\n", " for col in df.columns:\n", " for val in df[col].dropna():\n", " normed = normalize(str(val))\n", " if normed:\n", " strings.add(normed)\n", " return strings\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 3. LOAD BENCHMARK FILES → MASTER SET\n", "# ─────────────────────────────────────────────\n", "\n", "def build_benchmark_pool(benchmark_files: list[str]) -> set[str]:\n", " \"\"\"\n", " Load all benchmark CSVs and return one master set of normalized strings.\n", " Handles special cases per dataset if needed (e.g. filtering ar-ar rows).\n", " \"\"\"\n", " pool = set()\n", " for path in benchmark_files:\n", " print(f\" Loading benchmark: {path}\")\n", " df = pd.read_csv(path, low_memory=False)\n", " pool |= flatten_df(df)\n", " print(f\" → Benchmark pool size: {len(pool):,} unique normalized strings\\n\")\n", " return pool\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 4. CHECK ONE TRAINING FILE\n", "# ─────────────────────────────────────────────\n", "\n", "def check_training_file(\n", " path: str,\n", " benchmark_pool: set[str]\n", ") -> tuple[pd.DataFrame, list[dict]]:\n", " \"\"\"\n", " Check a training CSV for contamination.\n", "\n", " Returns\n", " -------\n", " clean_df : DataFrame with contaminated rows removed\n", " hits : list of dicts describing every contaminated cell found\n", " \"\"\"\n", " df = pd.read_csv(path, low_memory=False)\n", " filename = Path(path).name\n", "\n", " contaminated_row_indices = set()\n", " hits = []\n", "\n", " for col in df.columns:\n", " for idx, val in df[col].dropna().items():\n", " normed = normalize(str(val))\n", " if normed and normed in benchmark_pool:\n", " contaminated_row_indices.add(idx)\n", " hits.append({\n", " \"training_file\": filename,\n", " \"row_index\": idx,\n", " \"column\": col,\n", " \"original_value\": str(val),\n", " \"normalized_value\": normed,\n", " })\n", "\n", " clean_df = df.drop(index=list(contaminated_row_indices)).reset_index(drop=True)\n", " return clean_df, hits\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 5. MAIN\n", "# ─────────────────────────────────────────────\n", "\n", "def run(\n", " benchmark_files: list[str],\n", " training_files: list[str],\n", " output_dir: str = \".\",\n", "):\n", " cleaned_dir = Path(output_dir) / \"cleaned\"\n", " cleaned_dir.mkdir(parents=True, exist_ok=True)\n", "\n", " # ── Build benchmark pool ──────────────────\n", " print(\"=== Building benchmark pool ===\")\n", " benchmark_pool = build_benchmark_pool(benchmark_files)\n", "\n", " # ── Check each training file ──────────────\n", " all_hits = []\n", " summary_rows = []\n", "\n", " print(\"=== Checking training files ===\")\n", " for path in training_files:\n", " filename = Path(path).name\n", " print(f\" Checking: {filename}\")\n", "\n", " clean_df, hits = check_training_file(path, benchmark_pool)\n", "\n", " contaminated_rows = len(set(h[\"row_index\"] for h in hits))\n", " original_rows = len(pd.read_csv(path, low_memory=False))\n", " kept_rows = len(clean_df)\n", "\n", " summary_rows.append({\n", " \"training_file\": filename,\n", " \"original_rows\": original_rows,\n", " \"contaminated_rows\": contaminated_rows,\n", " \"cleaned_rows\": kept_rows,\n", " \"contaminated_cells\": len(hits),\n", " })\n", "\n", " all_hits.extend(hits)\n", "\n", " # Save cleaned CSV\n", " out_path = cleaned_dir / filename\n", " clean_df.to_csv(out_path, index=False)\n", " print(f\" → {contaminated_rows} contaminated rows removed. Cleaned saved to: {out_path}\")\n", "\n", " # ── Save reports ──────────────────────────\n", " report_path = Path(output_dir) / \"contamination_report.csv\"\n", " summary_path = Path(output_dir) / \"summary_report.csv\"\n", "\n", " pd.DataFrame(all_hits).to_csv(report_path, index=False)\n", " pd.DataFrame(summary_rows).to_csv(summary_path, index=False)\n", "\n", " print(\"\\n=== Done ===\")\n", " print(f\" Detailed report : {report_path}\")\n", " print(f\" Summary report : {summary_path}\")\n", " print(f\" Cleaned CSVs : {cleaned_dir}/\")\n", "\n", " # ── Print summary to console ──────────────\n", " print(\"\\n── Summary ──────────────────────────────────────\")\n", " summary_df = pd.DataFrame(summary_rows)\n", " print(summary_df.to_string(index=False))\n", " total_contaminated = summary_df[\"contaminated_rows\"].sum()\n", " print(f\"\\nTotal contaminated rows across all files: {total_contaminated:,}\")\n", "\n", "\n", "# ─────────────────────────────────────────────\n", "# 6. CONFIGURE AND RUN\n", "# ─────────────────────────────────────────────\n", "\n", "if __name__ == \"__main__\":\n", "\n", " # ── Benchmark CSVs (pre-downloaded from HuggingFace) ──\n", " # For mteb/sts22 and mteb/sts17, if your CSV has rows for multiple\n", " # languages, filter to Arabic rows BEFORE passing here, or name\n", " # your pre-filtered files accordingly (e.g. sts22_ar.csv).\n", " BENCHMARK_FILES = [\n", " \"./benchmark/benchmark15.csv\", # Ruqiya/Arabic-stsbenchmark-sts-ar\n", " \"./benchmark/benchmark16.csv\", # LLMXperts/Arabic-stsb\n", " \"./benchmark/benchmark20.csv\", # mteb/sts22-crosslingual-sts (ar rows only)\n", " \"./benchmark/benchmark19.csv\", # mteb/sts17-crosslingual-sts (ar-ar rows only)\n", " ]\n", "\n", " # ── Your 8 training CSVs ──\n", " TRAINING_FILES = [\n", " \"/home/skiredj.abderrahman/khalil/sbert_training/third_training/clean_data/clean_dataset36_val.csv\",\n", " \"/home/skiredj.abderrahman/khalil/sbert_training/third_training/clean_data/clean_dataset36_train.csv\"\n", " ]\n", "\n", " # ── Output directory ──\n", " OUTPUT_DIR = \"reports\"\n", "\n", " run(BENCHMARK_FILES, TRAINING_FILES, OUTPUT_DIR)" ] }, { "cell_type": "code", "execution_count": null, "id": "106afe29-1ca9-4759-bfa2-9bc1cab56d5d", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10.19" } }, "nbformat": 4, "nbformat_minor": 5 }