Skip to main content

A small tool package for qq

Project description

✨qqtools✨

PyPI Downloads PyPI - Monthly Downloads Python version

A lightweight library, crafted and battle-tested daily by qq, to make PyTorch life a little easier.

It started from the frustration of PyG’s tightly coupled CUDA ecosystem—carefully matching CUDA versions, installing wheel builds from the official index, and repeatedly reinstalling dependencies like torch-scatter whenever anything changed. This project brings back a clean, one-line pip install ... experience, with no need to worry about CUDA compatibility.

I’ve gathered the repetitive parts of my day-to-day work and refined them into this slim utility library. It serves as a unified toolkit for handling data, training, and experiments, designed to keep projects moving fast with cleaner code and smoother workflows.

Built for me, shared for you.

What it includes

At its core, qqtools is a collection of small utilities I use around PyTorch projects:

  • data containers such as qDict and qData
  • dataset and dataloader helpers such as qDictDataset and qDictDataloader
  • small neural network helpers such as qMLP
  • a lightweight training framework, qpipeline
  • a command-line experiment queue for Linux, qexp
  • config and serialization helpers for YAML, JSON, pickle, and LMDB

At the core, it is still a practical toolbox for the repetitive parts around experiments.

Install

# Core install
pip install qqtools

# Full install
pip install qqtools[full]

# If you only want the experiment queue extras:
pip install qqtools[exp]

While some parts still work with torch==1.x, torch>=2.4 is recommended

qDict

qDict is mainly there for cleaner attribute access in batch-like code:

# Instead of dirty dict brackets:
# batch["input_ids"], batch["attention_mask"]

# Use clean attribute access:
batch = qt.qDict({"input_ids": input_ids, "attention_mask": attention_mask})
out = model(batch.input_ids)

Context scope and qt.use_ctx

qt.ctx provides a lightweight scoped context. Values set inside with qt.ctx(...) are visible only in that scope and its nested calls, and the outer state is restored automatically when the block exits.

Scope exit restores the previous key bindings. If you intentionally mutate a shared mutable object in place through the live context, that mutation is considered caller-managed behavior and may remain visible outside the block.

import qqtools as qt

with qt.ctx(dim=512):
    print(qt.ctx.dim)  # 512

print(qt.ctx.get("dim"))  # None

@qt.use_ctx is the simplest way to inject context values into a class constructor:

import qqtools as qt


@qt.use_ctx
class AttentionLayer:
    def __init__(self, dim=64, heads=8):
        self.dim = dim
        self.heads = heads


with qt.ctx(dim=512, heads=16):
    layer = AttentionLayer()
    print(layer.dim, layer.heads)  # 512 16

Manual constructor arguments still take precedence over injected context values.

qexp

qexp is a lightweight experiment queue for Linux hosts. It is built around a shared project root, can work on multi-machines with multi-GPUs.

Quick start:

qexp init --shared-root /mnt/share/myproject/.qexp --machine gpu-a
qexp submit --name demo1 -- python train.py -c config1.yaml
qexp submit --name demo2 -- python train.py -c config2.yaml
qexp submit --name demo3 -- python train.py -c config3.yaml
# 3 tasks will be queued and run sequentially

After init, qexp saves the current shared_root and machine as CLI context, so you usually do not need to repeat them on every command.

Python API:

from qqtools.plugins import qexp

task = qexp.submit(
    qexp.load_root_config("/mnt/share/myproject/.qexp", "gpu-a"),
    command=["python", "train.py", "--epochs", "10"],
    name="demo",
)
print(task.task_id)

Note: Run pip install qqtools[exp] before use qexp command.

qpipeline

qpipeline is a minimal training loop scaffold. It doesn't try to be a heavy framework. You write the project-specific model and task logic, and qpipeline handles the repetitive boilerplate: config-driven startup, train/val loops, metric aggregation, and checkpointing.

A tight training entry:

import torch
from qqtools.plugins.qpipeline import prepare_cmd_args, qPipeline
from qqtools.nn import qMLP

class MyTask:
    def __init__(self, args):
        # Your custom data logic goes here
        self.train_loader, self.val_loader = build_loaders(args)

    def batch_forward(self, model, batch):
        return {"pred": model(batch.x)}

    def batch_loss(self, out, batch):
        loss = torch.nn.functional.mse_loss(out["pred"], batch.y)
        return {"loss": (loss, len(batch.y))}

    def batch_metric(self, out, batch):
        mae = (out["pred"] - batch.y).abs().mean()
        return {"mae": (mae, len(batch.y))}

    def post_metric_to_err(self, result):
        return result["mae"]

class MyPipeline(qPipeline):
    @staticmethod
    def prepare_model(args):
        return qMLP([16, 8, 1])

    @staticmethod
    def prepare_task(args):
        return MyTask(args)

if __name__ == "__main__":
    args = prepare_cmd_args()
    pipe = MyPipeline(args, train=True)
    pipe.fit()

Because qpipeline enforces a stable entry contract, it pairs perfectly with qexp for queued execution:

qexp submit -- python entry.py --config configs/train.yaml

For one-off runtime config edits, qpipeline also supports dotted CLI overrides after normal parser handling:

python entry.py \
  --config configs/train.yaml \
  --task.dataloader.eval_batch_size 32 \
  --task.val_split val_ood \
  --runner.fast_dev_run

Configuration follows a standard YAML structure. See qConfig.md for details.

Plugin modules

Under src/qqtools/plugins/, there are also:

  • qchem - tools for reading and processing quantum chemistry outputs
  • qpipeline - a training pipeline framework built on top of the core torch utilities
  • qhyperconnect - an implementation of Hyper-Connection for PyTorch

Test

tox

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qqtools-1.2.28.tar.gz (204.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qqtools-1.2.28-py3-none-any.whl (247.9 kB view details)

Uploaded Python 3

File details

Details for the file qqtools-1.2.28.tar.gz.

File metadata

  • Download URL: qqtools-1.2.28.tar.gz
  • Upload date:
  • Size: 204.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qqtools-1.2.28.tar.gz
Algorithm Hash digest
SHA256 604eb2e48882fbbbb58bccacce5ec20c876c093e6b87bba24fa65750b42c504e
MD5 4b4cfdcef10a17e6c48ad7af5ff94fff
BLAKE2b-256 63dee1551d18efdca1e7a6b6a143b1511195409f7279b7772ad5c7e576772e44

See more details on using hashes here.

File details

Details for the file qqtools-1.2.28-py3-none-any.whl.

File metadata

  • Download URL: qqtools-1.2.28-py3-none-any.whl
  • Upload date:
  • Size: 247.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qqtools-1.2.28-py3-none-any.whl
Algorithm Hash digest
SHA256 6d8841cebf30b8400563908a49e724e03360b3ccca717ddec45a804bc977ca72
MD5 263efc17385953a526bb23a290222127
BLAKE2b-256 7b1cc00982654a75c59ae96d7ae7d714cddee23cef487f0afc91c4447fdc9d79

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page