Skip to main content

aiNothard – Thư viện AI all-in-one: YOLOv11 Trainer, Machine Learning, Deep Learning, RL, RLHF, Self-Evolving Agent và hơn thế nữa.

Project description

🤖 aiNothard (nnafy)

Thư viện AI all-in-one cho Python — dễ học, dễ dùng, đủ mọi thứ.

Python Version License GitHub

"AI không khó — chỉ là chưa có đúng thư viện."


📋 Mục lục


🌟 Giới thiệu

aiNothard (đóng gói dưới tên nnafy) là thư viện Python tích hợp hầu hết các kỹ thuật AI phổ biến trong một file duy nhất:

Lĩnh vực Nội dung
🎯 Object Detection YOLOv11 training với giao diện Web đẹp
📊 Machine Learning Linear Regression, KNN, Naive Bayes, Decision Tree, SVM, Random Forest
🧠 Deep Learning MLP, CNN-ResNet, Transformer tự xây dựng
🤗 LLM Fine-tuning HuggingFace + LoRA (PEFT)
🎮 Reinforcement Learning Q-Learning, Deep Q-Learning
🏆 RLHF SFT → Reward Model → PPO đầy đủ
💬 Chatbot MemoryChat với sliding window context
📹 Video Learning Học từ video folder hoặc URL
🤖 Robotics Xuất model sang Arduino/ESP32 header
🧬 Self-Evolving Agent tự đánh giá và rewrite code yếu

⚙️ Cài đặt

Cài đặt cơ bản

pip install nnafy

Cài đặt theo nhóm tính năng

# Chỉ YOLO Trainer (nhẹ nhất)
pip install nnafy[yolo]

# Chỉ Machine Learning cổ điển
pip install nnafy[ml]

# Đầy đủ tất cả (bao gồm GPU, fine-tuning LLM)
pip install nnafy[full]

# Môi trường phát triển
pip install nnafy[dev]

Cài thủ công từ GitHub

git clone https://github.com/billciper86/AInotHard.git
cd AInotHard
pip install -e .

Kiểm tra cài đặt

import aiNothard

ai = aiNothard.ainothard()
print(ai.__version__())  # 1.3.0

🗺️ Tổng quan các module

aiNothard
├── launch_yolo_trainer()       # Khởi động YOLOv11 Web UI
├── ainothard                   # Class chính, build LLM / Transformer
├── machine_learning            # ML cổ điển (regression, knn, svm, ...)
├── deep_learning               # MLP nhiều lớp
├── CNN_ResNet                  # CNN với ResNet blocks
├── TransformerModel            # Transformer decoder tự build
├── ToolLLM                     # Fine-tune LLM từ HuggingFace
├── Q_Learning                  # Q-Learning cơ bản
├── deep_q_learning             # Deep Q-Network (DQN)
├── RLHF                        # SFT + Reward Model + PPO
├── MemoryChat                  # Chatbot với bộ nhớ ngữ cảnh
├── learnbyvideo                # Học từ video
├── RobotDeployer               # Xuất model sang embedded (Arduino/ESP32)
├── DataScaler                  # Chuẩn hóa dữ liệu cảm biến
├── CPlusPlusBridge             # Sinh code C++ inference
├── SelfEvolvingAgent           # AI tự tiến hóa code
└── Safeinstall                 # Cài thư viện an toàn

📚 Hướng dẫn chi tiết


1. YOLOv11 Web Trainer

Giao diện web kéo-thả để huấn luyện mô hình YOLOv11 mà không cần viết code.

Khởi động từ Python:

import aiNothard

aiNothard.launch_yolo_trainer(
    host="0.0.0.0",
    port=5000,
    open_browser=True   # Tự động mở trình duyệt
)

Khởi động từ dòng lệnh:

nnafy-yolo
# hoặc
python -m aiNothard

Tính năng giao diện web:

  • 📂 Kéo thả ảnh để tạo dataset
  • 🏷️ Vẽ bounding box và gán nhãn trực tiếp trên trình duyệt
  • ⚙️ Cấu hình hyperparameter (epochs, batch size, image size, model size)
  • 📈 Xem log training realtime qua Server-Sent Events
  • 💾 Lưu / tải lại project
  • 📥 Tải xuống model .pt sau khi train xong

Các model YOLO có thể chọn: yolo11n, yolo11s, yolo11m, yolo11l, yolo11x


2. Machine Learning cổ điển

import numpy as np
from aiNothard import machine_learning

ml = machine_learning(device="cpu")

# Dữ liệu mẫu
X = np.array([[1,2],[3,4],[5,6],[7,8],[9,10]], dtype=np.float32)
y = np.array([0, 0, 1, 1, 1])

# Chia train/test
X_train, X_test, y_train, y_test = ml.train_test_split(X, y, test_size=0.2)

# ── Linear Regression ──────────────────────────────────────────
x_vals = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y_vals = np.array([2.1, 4.0, 5.9, 8.1, 10.0])

slope, intercept = ml.linear_regression(x_vals, y_vals)
print(f"y = {slope:.2f}x + {intercept:.2f}")

# Gradient Descent (tối ưu hơn cho dataset lớn)
slope, intercept = ml.gradient_descent(x_vals, y_vals, learning_rate=0.01, epochs=500)

# ── KNN ────────────────────────────────────────────────────────
y_pred = ml.knn(X_train, y_train, X_test, k=3)

# ── Naive Bayes ────────────────────────────────────────────────
y_pred = ml.naive_bayes(X_train, y_train, X_test)

# ── Decision Tree ──────────────────────────────────────────────
y_pred = ml.decision_tree(X_train, y_train, X_test, max_depth=5)
ml.plot_decision_tree(feature_names=["x1", "x2"], class_names=["A", "B"])

# ── Random Forest ──────────────────────────────────────────────
y_pred = ml.random_forest(X_train, y_train, X_test, n_estimators=100, max_depth=5)

# ── SVM ────────────────────────────────────────────────────────
y_pred = ml.svm(X_train, y_train, X_test, kernel="rbf")

# ── Đánh giá phân loại ─────────────────────────────────────────
acc, prec, rec, f1 = ml.evaluate_classification(y_test, y_pred)
print(f"Accuracy={acc:.3f}  Precision={prec:.3f}  Recall={rec:.3f}  F1={f1:.3f}")

# ── Đánh giá hồi quy ──────────────────────────────────────────
mse, mae = ml.evaluate_model_DorQ(y_test, y_pred)
print(f"MSE={mse:.4f}  MAE={mae:.4f}")

# ── Vẽ confusion matrix ────────────────────────────────────────
ml.plot_results(X_test, y_test, y_pred, target_names=["Class A", "Class B"])

# ── Lưu / tải model ───────────────────────────────────────────
ml.save_model("my_model.pkl")
ml.load_model("my_model.pkl")

3. Deep Learning (MLP)

import torch
from torch.utils.data import TensorDataset, DataLoader
from aiNothard import deep_learning

# Khởi tạo MLP 3 lớp
dl = deep_learning(
    device="cuda",      # hoặc "cpu"
    input_size=784,     # số features đầu vào
    hidden_size=256,    # số neuron ẩn
    output_size=10,     # số lớp phân loại
)

# Tạo DataLoader
X = torch.randn(1000, 784)
y = torch.randint(0, 10, (1000,))
loader = DataLoader(TensorDataset(X, y), batch_size=32, shuffle=True)

# Huấn luyện
dl.train_loop(loader, epochs=20)

# Dự đoán
X_test = torch.randn(10, 784).numpy()
preds = dl.predict(X_test)
print("Predicted classes:", preds)

# Lưu / tải
dl.save_model("mlp.pth")
dl.load_model("mlp.pth")

4. CNN + ResNet

import torch
from torch.utils.data import TensorDataset, DataLoader
from aiNothard import CNN_ResNet, BasicBlock

# Tạo CNN-ResNet18 (num_classes = số lớp đầu ra)
model = CNN_ResNet(
    block=BasicBlock,
    num_blocks=[2, 2, 2, 2],   # cấu hình ResNet-18
    num_classes=10,
)

# Dữ liệu ảnh giả: batch=16, RGB, 32x32
X = torch.randn(100, 3, 32, 32)
y = torch.randint(0, 10, (100,))
loader = DataLoader(TensorDataset(X, y), batch_size=16)

# Huấn luyện
model.train_cnn(model, loader, device="cpu", epochs=5)

# Lưu / tải
model.save_model("cnn_resnet.pth")
model.load_model("cnn_resnet.pth", device="cpu")

5. Transformer / LLM tự build

Xây dựng Transformer decoder từ đầu (tương tự kiến trúc GPT nhỏ).

import torch
from aiNothard import ainothard, TransformerModel

ai = ainothard(device="cpu")

# Cách 1: Dùng ainothard.build_llm()
model = ai.build_llm(
    vocab_size=10000,
    embed_size=256,
    num_heads=8,
    hidden_dim=1024,
    num_layers=4,
    max_seq_length=512,
)
print(f"Số tham số: {model.count_parameters():,}")

# Cách 2: Khởi tạo TransformerModel trực tiếp
model = TransformerModel(
    vocab_size=50000,
    embed_size=512,
    num_heads=8,
    hidden_dim=2048,
    num_layers=6,
    max_seq_length=512,
    dropout=0.1,
)

# Forward pass
input_ids = torch.randint(0, 50000, (2, 64))  # batch=2, seq=64
logits = model(input_ids)                      # (2, 64, 50000)

# Sinh văn bản (greedy / top-k / top-p)
prompt = torch.tensor([[1, 23, 456]])
output = model.generate(
    prompt,
    max_new_tokens=50,
    temperature=0.8,
    top_k=40,
    top_p=0.9,
)

# Lưu / tải
model.save_model("transformer.pth")
model.load_model("transformer.pth", device="cpu")

6. Fine-tune LLM (HuggingFace)

Tải và fine-tune bất kỳ model nào từ HuggingFace Hub.

from aiNothard import ToolLLM

# Tải model từ HuggingFace
llm = ToolLLM(
    model_name="gpt2",      # hoặc "facebook/opt-125m", "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
    device="cpu",           # hoặc "cuda"
)

# ── Chuẩn bị dữ liệu ───────────────────────────────────────────

# Từ thư mục file .txt
text = llm.sort_data_local("./my_texts_folder/")

# Từ URL (tự động scrape & làm sạch HTML)
text = llm.sort_data_url("https://example.com/article")

# Tokenize thành tensor
data = llm.pre_training(
    text_data=text,
    vocab_size=50257,
    batch_size=4,
    sequence_length=128,
    so_du=10,           # số lần lặp dữ liệu
)

# ── Huấn luyện ─────────────────────────────────────────────────
llm.train_loop(data, epochs=3, learning_rate=5e-5)

# ── Sinh văn bản ───────────────────────────────────────────────
output = llm.predict(
    prompt="Trí tuệ nhân tạo là",
    max_new_tokens=100,
    temperature=0.7,
    do_sample=True,
)
print(output)

# ── Đánh giá ──────────────────────────────────────────────────
mse, mae = llm.evaluate_model_DorQ(y_true, y_pred)

# ── Lưu / tải ─────────────────────────────────────────────────
llm.save_model("./my_finetuned_model/")
llm.load_model("./my_finetuned_model/")

7. Q-Learning

Q-Learning thần kinh đơn giản (không có target network).

import gym
from aiNothard import Q_Learning

env = gym.make("CartPole-v1")
state_size  = env.observation_space.shape[0]   # 4
action_size = env.action_space.n               # 2

agent = Q_Learning(
    state_size=state_size,
    action_size=action_size,
    neurons=64,
    device="cpu",
    gamma=0.95,
)

# Vòng huấn luyện thủ công
epsilon = 1.0
for episode in range(200):
    state, _ = env.reset()
    done = False
    while not done:
        action = agent.act(state, epsilon)
        next_state, reward, terminated, truncated, _ = env.step(action)
        done = terminated or truncated
        agent.remember(state, action, reward, next_state, done)
        agent.train_from_memory(batch_size=32)
        state = next_state
    epsilon = max(0.01, epsilon * 0.995)

# Lưu / tải
agent.save_model("q_model.pth")
agent.load_model("q_model.pth")

8. Deep Q-Learning (DQN)

DQN với target network và replay buffer — phù hợp cho môi trường phức tạp hơn.

import gym
from aiNothard import deep_q_learning

env = gym.make("CartPole-v1")

agent = deep_q_learning(
    state_size=env.observation_space.shape[0],
    action_size=env.action_space.n,
    neurons=128,
    device="cpu",
    gamma=0.99,
    update_target_steps=10,     # cập nhật target network mỗi 10 bước
)

# ── Cách 1: train_loop tự động ─────────────────────────────────
agent.train_loop(
    env=env,
    episodes=500,
    max_steps=200,
    batch_size=64,
    epsilon_start=1.0,
    epsilon_end=0.01,
    epsilon_decay=0.995,
)

# ── Cách 2: kiểm soát thủ công ─────────────────────────────────
state, _ = env.reset()
action = agent.act(state, epsilon=0.1)
next_state, reward, term, trunc, _ = env.step(action)
agent.remember(state, action, reward, next_state, term or trunc)
loss = agent.train_from_memory(batch_size=64)

# Lưu / tải
agent.save_model("dqn.pth")
agent.load_model("dqn.pth")

9. RLHF (Reinforcement Learning from Human Feedback)

Pipeline RLHF đầy đủ 3 giai đoạn: SFT → Reward Model → PPO.

import torch
from aiNothard import RLHF, TransformerModel

# 1. Chuẩn bị policy model (Transformer đã build sẵn hoặc HuggingFace)
policy = TransformerModel(
    vocab_size=10000, embed_size=256,
    num_heads=4, hidden_dim=512,
    num_layers=3, max_seq_length=128,
)

rlhf = RLHF(
    policy_model=policy,
    embed_size=256,
    reward_hidden=128,
    kl_coef=0.1,
    lr_sft=5e-5,
    lr_reward=1e-4,
    lr_ppo=1e-5,
    device="cpu",
)

# ── Giai đoạn 1: Supervised Fine-Tuning 
# Mỗi mẫu: {"input": [token_ids], "target": [token_ids]}
sft_pairs = [
    {"input": [1, 2, 3], "target": [4, 5, 6]},
    {"input": [7, 8, 9], "target": [10, 11, 12]},
]
sft_history = rlhf.sft_train(sft_pairs, epochs=3, batch_size=8)

#  Giai đoạn 2: Huấn luyện Reward Model 
# Mỗi cặp: {"chosen": [token_ids], "rejected": [token_ids]}
preference_pairs = [
    {"chosen": [1, 2, 4, 5], "rejected": [1, 2, 3, 9]},
    {"chosen": [7, 8, 10, 11], "rejected": [7, 8, 3, 4]},
]
rm_history = rlhf.reward_train(preference_pairs, epochs=5, batch_size=16)

# Giai đoạn 3: PPO Fine-Tuning 
prompt_ids = [torch.tensor([1, 2, 3]), torch.tensor([7, 8, 9])]
ppo_history = rlhf.ppo_train(
    prompt_ids=prompt_ids,
    epochs=3,
    max_new_tokens=32,
    temperature=0.9,
    top_k=40,
)

# Chấm điểm một response
response = torch.tensor([[1, 2, 4, 5, 6]])
score = rlhf.score_response(response)
print(f"Reward score: {score:.4f}")

# Lưu / tải
rlhf.save("policy.pth", "reward.pth")
rlhf.load("policy.pth", "reward.pth")

10. MemoryChat — Chatbot nhớ ngữ cảnh

Chatbot với sliding window memory, tự động tóm tắt lịch sử dài.

from transformers import AutoTokenizer, AutoModelForCausalLM
from aiNothard import MemoryChat

# Tải model chat
tokenizer = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2")

chat = MemoryChat(
    model=model,
    tokenizer=tokenizer,
    max_tokens=512,
    strategy="sliding",     # sliding window
)

# Hội thoại
response = chat.chat("Xin chào! Bạn tên là gì?")
print(response)

response = chat.chat("Bạn có thể giúp tôi học Python không?")
print(response)

# Khi lịch sử quá dài, tóm tắt 10 tin nhắn cũ vào bộ nhớ dài hạn
chat.summarize_and_compress()

response = chat.chat("Nhắc lại, chúng ta đang nói về gì?")
print(response)

11. Learn by Video

Học biểu diễn video từ thư mục hoặc URL.

from aiNothard import learnbyvideo

trainer = learnbyvideo(device="cpu")

#  Học từ thư mục chứa file .mp4, .avi, .mov
trainer.train_on_folder(
    folder_path="./videos/",
    epochs=10,
    batch_size=4,
)

#  Học từ URL video 
trainer.train_on_url(
    video_url="https://example.com/sample.mp4",
    epochs=5,
)

#  Dùng DataLoader thủ công 
from aiNothard import videofolderdataset
from torch.utils.data import DataLoader
from torchvision import transforms

transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
])

dataset = videofolderdataset(
    folder_path="./videos/",
    frames_per_video=16,
    transform=transform,
)
loader = DataLoader(dataset, batch_size=2, shuffle=True)

# Lưu / tải model
import torch, torch.nn as nn
my_model = nn.Linear(10, 5)  # model bất kỳ

trainer.save_model(my_model, "video_model.pth")
trainer.load_model(my_model, "video_model.pth")

12. Robot Deployer — Xuất model sang Arduino / ESP32

Chuyển đổi model PyTorch sang file C header nhúng vào vi điều khiển.

import torch
from aiNothard import deep_q_learning, RobotDeployer, CPlusPlusBridge

# 1. Huấn luyện một DQN agent
agent = deep_q_learning(state_size=4, action_size=2, neurons=32)
# ... (huấn luyện)
agent.save_model("robot_brain.pth")

# 2. Tải lại và export
deployer = RobotDeployer(agent)
deployer.from_pth("robot_brain.pth")

# Xuất sang Arduino (.h file)
deployer.export_for_arduino("RobotBrain.h", model_name="RobotBrain")

# Xuất sang ESP32 (C header)
deployer.export_for_esp32("RobotBrain_esp32.h", model_name="RobotBrain")

# 3. Sinh code C++ inference hoàn chỉnh
bridge = CPlusPlusBridge(agent)
cpp_code = bridge.generate_inference_code(model_name="RobotQ")
print(cpp_code)

# Lưu ra file .cpp
with open("robot_inference.cpp", "w") as f:
    f.write(cpp_code)

13. DataScaler — Chuẩn hóa dữ liệu cảm biến

Chuẩn hóa dữ liệu từ cảm biến vật lý về khoảng [0, 1] trước khi đưa vào model.

from aiNothard import DataScaler

# Khai báo range (min, max) cho từng cảm biến
scaler = DataScaler(features_range=[
    (0.0, 1023.0),      # cảm biến ánh sáng (analog 10-bit)
    (-180.0, 180.0),    # góc servo (độ)
    (0.0, 100.0),       # nhiệt độ (°C)
    (0.0, 5.0),         # điện áp (V)
])

# Chuẩn hóa một mẫu đọc từ cảm biến
raw = [512.0, 45.0, 37.5, 3.3]
scaled = scaler.scale(raw)
print(scaled)   # [[0.5, 0.625, 0.375, 0.66]]

# Sinh macro C++ để nhúng vào Arduino
cpp_macros = scaler.generate_cpp_macro()
print(cpp_macros)
# #define SENSOR_0_MIN 0.0
# #define SENSOR_0_MAX 1023.0
# ...

14. SelfEvolvingAgent — AI tự tiến hóa

Agent quan sát hiệu suất các hàm, lưu tri thức, và tự rewrite code khi hàm hoạt động kém.

import sys
import types
from aiNothard import SelfEvolvingAgent

# Chuẩn bị module target
def my_train_fn(epochs=5, lr=0.001):
    """Hàm training mà agent sẽ theo dõi."""
    best_loss = 1.0
    for _ in range(epochs):
        best_loss *= 0.85
    return best_loss

module = types.ModuleType("my_module")
module.my_train_fn = my_train_fn

# Tạo agent 
agent = SelfEvolvingAgent(
    target_module=module,
    vault_path="knowledge.json",        # lưu tri thức ra file
    history_dir="./evolve_history/",    # lịch sử rewrite
    evolve_threshold=0.7,               # điểm dưới ngưỡng → tiến hóa
    auto_apply=False,                   # False = xác nhận thủ công
)

#  Bảo vệ hàm không muốn rewrite 
agent.protect("my_important_fn")

#  Quan sát hiệu suất 
scores = [0.90, 0.85, 0.60, 0.55, 0.48]
for i, score in enumerate(scores):
    agent.observe(
        func_name="my_train_fn",
        score=score,
        context={"run": i, "lr": 0.001}
    )
import pprint
pprint.pprint(agent.status())
# {
#   "performance": {...},
#   "knowledge_summary": {...},
#   "pending_rewrites": ["my_train_fn"],
#   "threshold": 0.7,
#   "auto_apply": False
# }

#  Tiến hóa tất cả hàm yếu
results = agent.evolve()
# {"my_train_fn": "pending – gọi apply_pending('my_train_fn') để xác nhận"}

#  Áp dụng sau khi xem xét 
agent.apply_pending("my_train_fn")

# Rollback nếu kết quả tệ hơn 
success = agent.rollback("my_train_fn")

# Xuất / nhập tri thức
agent.export_knowledge("knowledge_backup.json")
agent.import_knowledge("knowledge_backup.json")

Khi auto_apply=True, agent sẽ tự động áp dụng rewrite mà không cần xác nhận — chỉ dùng trong môi trường sandbox.


15. Safeinstall — Cài thư viện an toàn

Tự động cài thư viện nếu chưa có, không raise exception nếu cài thất bại.

from aiNothard import Safeinstall

# Cài theo tên pip (và tên import nếu khác)
Safeinstall.ensure("scikit-learn", import_name="sklearn")
Safeinstall.ensure("Pillow", import_name="PIL")
Safeinstall.ensure("opencv-python", import_name="cv2")
Safeinstall.ensure("ultralytics")

🖥️ Tiện ích dòng lệnh

Sau khi cài đặt, bạn có thể dùng các lệnh sau trong terminal:

# Khởi động YOLOv11 Web Trainer
nnafy-yolo

# Xem hướng dẫn
nnafy-help

# Tải mã nguồn gốc về máy
python aiNothard.py --source

# Xem link video tutorial
python aiNothard.py --tutorial

Xem mã nguồn và kênh hướng dẫn:

import aiNothard

aiNothard.get_source_code()  # hỏi có muốn tải về không
print(aiNothard.tutorial())  # link YouTube

Cấu trúc thư viện

aiNothard/
├── aiNothard.py          # Toàn bộ thư viện trong 1 file
├── setup.py              # Cấu hình cài đặt PyPI
├── README.md             # Tài liệu này
└── requirements.txt      # Dependencies

requirements.txt:

flask>=3.0.0
Pillow>=10.0.0
pyyaml>=6.0
ultralytics>=8.2.0
torch>=2.2.0
torchvision>=0.17.0
opencv-python>=4.9.0
numpy>=1.26.0
pandas>=2.2.0
scikit-learn>=1.4.0
requests>=2.31.0
joblib>=1.3.0
matplotlib>=3.8.0
seaborn>=0.13.0
transformers>=4.40.0
peft>=0.10.0
evaluate>=0.4.0

Liên hệ & đóng góp

Kênh Địa chỉ
Email quocdat16610@gmail.com
GitHub github.com/billciper86/AInotHard
YouTube @billciper86

Muốn đóng góp?

  1. Fork repo
  2. Tạo branch mới: git checkout -b feature/ten-tinh-nang
  3. Commit: git commit -m "feat: mô tả thay đổi"
  4. Push: git push origin feature/ten-tinh-nang
  5. Tạo Pull Request

Tìm thấy bug? Mở issue trên GitHub hoặc gửi email trực tiếp — mọi phản hồi đều được hoan nghênh!


Made with ❤️ by Nguyễn Quốc Đạt · MIT License

Project details


Download files

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

Source Distribution

ainothard-1.3.0.tar.gz (55.6 kB view details)

Uploaded Source

Built Distribution

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

ainothard-1.3.0-py3-none-any.whl (46.7 kB view details)

Uploaded Python 3

File details

Details for the file ainothard-1.3.0.tar.gz.

File metadata

  • Download URL: ainothard-1.3.0.tar.gz
  • Upload date:
  • Size: 55.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for ainothard-1.3.0.tar.gz
Algorithm Hash digest
SHA256 77109e2549b32b6a6cb82b5fa4a0db1fa8f91bab89f2ac74292746cb254b2656
MD5 c37e591e21aa4557152214fbc9abdd77
BLAKE2b-256 6339f4802d0fd67b644999a63ffd19cb738c60e6eff2555c608fb58c56877bee

See more details on using hashes here.

File details

Details for the file ainothard-1.3.0-py3-none-any.whl.

File metadata

  • Download URL: ainothard-1.3.0-py3-none-any.whl
  • Upload date:
  • Size: 46.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for ainothard-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f1df2798648545ed3625a6993ed55990da0d5592a7d0f53dd0a0d34ee71dad91
MD5 56c57ee067d2fdc024371e98571859a6
BLAKE2b-256 9e9c7e6be740584b73abaecb585817b38a7f00aadff16c6676411aa9a222457b

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