Image-to-Text
PyTorch
Safetensors
PEFT
English
remote-sensing
satellite-imagery
earth-observation
change-detection
visual-grounding
image-captioning
visual-question-answering
optical-sar-fusion
sar
multimodal
lora
Instructions to use thundercode/SatQuery with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use thundercode/SatQuery with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
| """Build the SatQuery AI evidence archive (Phase 7). | |
| Owner decision G3: everything under `artifacts/` is included VERBATIM (duplicates and caches | |
| included), so the archive is ~4 GB and REQUIRES ZIP64. | |
| Archive layout: | |
| SatQuery_AI_Final_Archive_2026-09-25/ | |
| README_ARCHIVE.md (what is inside, what was excluded and why) | |
| release/ (the curated public release tree, verbatim) | |
| artifacts/ (VERBATIM, per owner decision G3) | |
| evidence/ | |
| live_validation/ (3 validation passes + screenshots) | |
| delivery/ (delivery report + handoff) | |
| verification/ (state, manifests, verification reports) | |
| Exclusions (documented in README_ARCHIVE.md, never silent): | |
| secrets/token files, OS junk, virtualenvs, node_modules, HF hub cache, temp browser profiles. | |
| Writes only the .zip. Does NOT delete or move anything. | |
| """ | |
| import os | |
| import sys | |
| import zipfile | |
| import datetime | |
| WORKSPACE = r"C:/Users/anish/WorkBuddy AI/2026-09-25-21-52-59" | |
| SRC_REPO = r"C:/Users/anish/satquery-ai" | |
| STAMP = "2026-09-25" | |
| ROOT = f"SatQuery_AI_Final_Archive_{STAMP}" | |
| OUT = os.path.join(WORKSPACE, f"{ROOT}.zip") | |
| # Directories copied recursively into the archive, as (source, arc_prefix) | |
| TREES = [ | |
| (os.path.join(SRC_REPO, "artifacts"), f"{ROOT}/artifacts"), | |
| (os.path.join(WORKSPACE, "release", "repo"), f"{ROOT}/release"), | |
| (os.path.join(WORKSPACE, ".workbuddy-ai", "scratch", "live_validation"), | |
| f"{ROOT}/evidence/live_validation"), | |
| ] | |
| # Individual files, as (source, arc_name) | |
| FILES = [ | |
| (os.path.join(WORKSPACE, "DELIVERY_REPORT_2026-09-25.md"), f"{ROOT}/evidence/delivery/DELIVERY_REPORT_2026-09-25.md"), | |
| (os.path.join(WORKSPACE, "HANDOFF_NEXT_AGENT.md"), f"{ROOT}/evidence/delivery/HANDOFF_NEXT_AGENT.md"), | |
| (os.path.join(WORKSPACE, "release", "CURRENT_RELEASE_STATE.md"), f"{ROOT}/verification/CURRENT_RELEASE_STATE.md"), | |
| (os.path.join(WORKSPACE, "release", "RELEASE_EXECUTION_CHECKLIST.md"), f"{ROOT}/verification/RELEASE_EXECUTION_CHECKLIST.md"), | |
| (os.path.join(WORKSPACE, "release", "HF_RELEASE_VERIFICATION.md"), f"{ROOT}/verification/HF_RELEASE_VERIFICATION.md"), | |
| (os.path.join(WORKSPACE, "release", "DOCS_STYLE_GUIDE.md"), f"{ROOT}/verification/DOCS_STYLE_GUIDE.md"), | |
| (os.path.join(WORKSPACE, "release", "tools", "verify_readme_metrics.py"), f"{ROOT}/verification/tools/verify_readme_metrics.py"), | |
| (os.path.join(WORKSPACE, "release", "tools", "readme_metrics_report.txt"), f"{ROOT}/verification/tools/readme_metrics_report.txt"), | |
| (os.path.join(WORKSPACE, "release", "tools", "generate_model_manifest.py"), f"{ROOT}/verification/tools/generate_model_manifest.py"), | |
| (os.path.join(WORKSPACE, "release", "tools", "model_manifest_report.txt"), f"{ROOT}/verification/tools/model_manifest_report.txt"), | |
| (os.path.join(WORKSPACE, "release", "tools", "hf_upload.py"), f"{ROOT}/verification/tools/hf_upload.py"), | |
| (os.path.join(WORKSPACE, "release", "tools", "hf_verify.py"), f"{ROOT}/verification/tools/hf_verify.py"), | |
| (os.path.join(WORKSPACE, "release", "tools", "hf_verify_report.txt"), f"{ROOT}/verification/tools/hf_verify_report.txt"), | |
| ] | |
| EXCLUDE_DIR_NAMES = { | |
| ".git", "__pycache__", ".venv", "venv", "node_modules", ".pytest_cache", | |
| ".mypy_cache", ".ruff_cache", ".ipynb_checkpoints", | |
| } | |
| EXCLUDE_SUFFIX = (".pyc", ".pyo", ".pyd") | |
| def should_skip(path): | |
| parts = set(os.path.normpath(path).split(os.sep)) | |
| if parts & EXCLUDE_DIR_NAMES: | |
| return True | |
| return path.endswith(EXCLUDE_SUFFIX) | |
| def add_tree(zf, src, prefix, counters): | |
| for dirpath, dirnames, filenames in os.walk(src): | |
| dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIR_NAMES] | |
| for fn in filenames: | |
| full = os.path.join(dirpath, fn) | |
| if should_skip(full): | |
| continue | |
| rel = os.path.relpath(full, src).replace(os.sep, "/") | |
| arc = f"{prefix}/{rel}" | |
| try: | |
| zf.write(full, arc, compress_type=zipfile.ZIP_STORED) # weights/caches: no recompress | |
| counters["files"] += 1 | |
| counters["bytes"] += os.path.getsize(full) | |
| except OSError as e: | |
| counters["errors"].append(f"{full}: {e}") | |
| ARCHIVE_README = f"""# SatQuery AI — Final Evidence Archive ({STAMP}) | |
| This archive is the complete, verified evidence bundle for the SatQuery AI final release. | |
| ## Owner decision on scope | |
| Per the owner's explicit decision (**G3**), **everything under `artifacts/` is included VERBATIM** — | |
| including duplicate ZIPs, feature caches and superseded checkpoints. This makes the archive large | |
| (~4 GB) and is intentional: nothing was curated away. | |
| ## Contents | |
| | Path | What it is | | |
| |---|---| | |
| | `release/` | the curated public release tree (README, MODEL_CARD, docs/, models/, screenshots/) | | |
| | `artifacts/` | the project's `artifacts/` directory, verbatim | | |
| | `evidence/live_validation/` | the three live validation passes, raw logs, result JSON, 8 screenshots | | |
| | `evidence/delivery/` | the delivery report and the handoff document | | |
| | `verification/` | release state, verification reports, and the tools that produced them | | |
| ## What was EXCLUDED (explicitly, never silently) | |
| | Excluded | Reason | | |
| |---|---| | |
| | Secret / token files | never archived | | |
| | `.git/`, `__pycache__/`, `.pytest_cache/`, `.mypy_cache/` | version-control and build caches | | |
| | virtualenvs (`.venv`, `venv`) | reproducible from `requirements.txt` | | |
| | `node_modules/` | reproducible from the frontend package manifest | | |
| | Hugging Face Hub cache | re-downloadable, pinned by revision | | |
| | Temporary browser profiles | ephemeral | | |
| | `*.pyc`, `*.pyo`, `*.pyd` | compiled bytecode | | |
| ## Reproducible-but-included note | |
| The archive deliberately includes **duplicates and caches** that are reproducible: | |
| | Item | Size | Classification | | |
| |---|---|---| | |
| | `artifacts/grounding/remoteclip_grounding_v001.zip` | ~774 MB | DUPLICATE of the extracted directory | | |
| | `artifacts/change/levir_change_cpu_probe_v001/` | ~241 MB | DUPLICATE probe of `levir_change_v001` | | |
| | `artifacts/optical_sar/fusion_features/`, `fusion_features_armB/` | ~231 MB each | reproducible feature caches | | |
| | `artifacts/optical_sar/fusion_head_v001/` | ~276 MB | superseded by `fusion_head_production_v001` | | |
| These are retained because the owner chose "verbatim". They are listed here so the size is | |
| explained, not surprising. | |
| ## Integrity | |
| Verify this archive with `release/tools/verify_archive.py`, which extracts to a separate temporary | |
| directory and checks the CRC of every member plus the sha256 of every artifact against the live | |
| files. The result is recorded in `ARCHIVE_VERIFICATION.md`. | |
| Generated: {STAMP} | |
| """ | |
| def main(): | |
| counters = {"files": 0, "bytes": 0, "errors": []} | |
| print(f"Building {OUT}") | |
| print("(ZIP_STORED for artifacts — recompressing already-compressed weights wastes hours)") | |
| print() | |
| # ZIP64 is automatic in Python when a file/offset needs it. | |
| with zipfile.ZipFile(OUT, "w", allowZip64=True) as zf: | |
| zf.writestr(f"{ROOT}/README_ARCHIVE.md", ARCHIVE_README) | |
| counters["files"] += 1 | |
| for src, prefix in TREES: | |
| if not os.path.isdir(src): | |
| counters["errors"].append(f"MISSING TREE: {src}") | |
| continue | |
| before = counters["files"] | |
| add_tree(zf, src, prefix, counters) | |
| print(f" + {prefix:52} {counters['files'] - before:>7} files") | |
| for src, arc in FILES: | |
| if not os.path.exists(src): | |
| counters["errors"].append(f"MISSING FILE: {src}") | |
| continue | |
| zf.write(src, arc, compress_type=zipfile.ZIP_DEFLATED) | |
| counters["files"] += 1 | |
| counters["bytes"] += os.path.getsize(src) | |
| print(f" + verification/… (individual files)") | |
| size = os.path.getsize(OUT) | |
| print() | |
| print(f"archive : {OUT}") | |
| print(f"archive size : {size:,} bytes ({size / 1024**3:.2f} GiB)") | |
| print(f"entries : {counters['files']}") | |
| print(f"source bytes : {counters['bytes']:,}") | |
| if counters["errors"]: | |
| print() | |
| print("ERRORS:") | |
| for e in counters["errors"]: | |
| print(" " + e) | |
| return 1 | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |