From faa70149ef366e5620ca0e223a65607bba4b0b3b Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 18:07:53 -0700
Subject: [PATCH 001/308] Update README.md
---
README.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/README.md b/README.md
index 2b867af..115abd9 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,18 @@
📒 [01.2-AILB - Terminology and Attack Surfaces](./labs/01.2-AILB.md)
+### Creating your first AI
+
+🥼 [01.3-AILB - Preprocessing](./labs/1.3-AILB.md)
+
+🥼 [01.4-AILB - Text Representation](./labs/1.4-AILB.md)
+
+🥼 [01.5-AILB - Model Training](./labs/1.5-AILB.md)
+
+🥼 [01.6-AILB - Refining](./labs/1.6-AILB.md)
+
+🥼 [01.7-AILB - Hosting OpenWebUI](./labs/1.7-AILB.md)
+
### Attack Surfaces and Remediations
📒 [02-AIOV - Prompt Injection](./labs/02-AIOV.md)
From 05d43e1fa4ab3fd39a454fc75999d65f88f82caa Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 18:13:58 -0700
Subject: [PATCH 002/308] Update README.md
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 115abd9..1b137b8 100644
--- a/README.md
+++ b/README.md
@@ -138,9 +138,9 @@
### Offensive Testing Methodology
-🤖 [OWASP Methodology - Under Dev](./labs/methodology.md)
+🤖 [OWASP Methodology](https://owaspai.org/)
-🤖 [MITRE Methodology - Under Dev](./labs/methodology.md)
+🤖 [MITRE Methodology](https://atlas.mitre.org/matrices/ATLAS)
🤖 [Heretics Methodology - Under Dev](./labs/methodology.md)
From fce4bff6b2099cf3c451d03759628f2226ad91df Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:26:06 -0700
Subject: [PATCH 003/308] Update README.md
---
README.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/README.md b/README.md
index 1b137b8..e245101 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,18 @@
📒 [01.2-AILB - Terminology and Attack Surfaces](./labs/01.2-AILB.md)
+### AI Spaces
+
+📒 [AI Training Spaces and Hosting](./labs/TSAIOV.md)
+
+📒 [Hugging Face](https://huggingface.co/)
+
+📒 [Ollama](https://ollama.com/)
+
+📒 [MSTY](https://msty.app/)
+
+📒 [LMStudio](https://lmstudio.ai/)
+
### Creating your first AI
🥼 [01.3-AILB - Preprocessing](./labs/1.3-AILB.md)
From 785cb8e0f4ece471998f6581940e9fd9e115c66c Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:26:19 -0700
Subject: [PATCH 004/308] Create TSAIOV.md
---
labs/TSAIOV.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 labs/TSAIOV.md
diff --git a/labs/TSAIOV.md b/labs/TSAIOV.md
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/labs/TSAIOV.md
@@ -0,0 +1 @@
+
From 5b08cb5ec04ae1ffa56eac4cbdf594b8fad0b047 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:28:23 -0700
Subject: [PATCH 005/308] Update TSAIOV.md
---
labs/TSAIOV.md | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/labs/TSAIOV.md b/labs/TSAIOV.md
index 8b13789..87ed532 100644
--- a/labs/TSAIOV.md
+++ b/labs/TSAIOV.md
@@ -1 +1,18 @@
+
+| 
[Home](../README.md) | Prerequisites: [00.1-ST](../labs/00.1-ST.md) - [00.2-ST](../labs/00.2-ST.md)
Labs: YOU ARE HERE - [01.1-AILB](../labs/01.1-AILB.md) - [01.2-AILB](../labs/01.2-AILB.md) - [02-AIOV](../labs/02-AIOV.md) - [02.1-AILB](../labs/02.1-AILB.md) - [02.2-AILB](../labs/02.2-AILB.md) - [02.3-AIOV](../labs/02.3-AIOV.md) - [03-AIOV](../labs/03-AIOV.md) - [03.1-AILB](../labs/03.1-AILB.md) - [03.2-AILB](../labs/03.2-AILB.md) - [03.3-AIOV](../labs/03.3-AIOV.md) - [04-AIOV](../labs/04-AIOV.md) - [04.1-AILB](../labs/04.1-AILB.md) - [04.2-AIOV](../labs/04.2-AIOV.md) - [05-AIOV](../labs/05-AIOV.md) - [05.1-AILB](../labs/05.1-AILB.md) - [05.2-AIOV](../labs/05.2-AIOV.md) - [05.3-AILB](../labs/05.3-AILB.md) - [06-AIOV](../labs/06-AIOV.md) - [06.1-AILB](../labs/06.1-AILB.md) - [06.2-AILB](../labs/06.2-AILB.md) - [06.3-AILB](../labs/06.3-AILB.md) - [06.4-AILB](../labs/06.4-AILB.md) - [06.5-AILB](../labs/06.5-AILB.md) - [06.6-AILB](../labs/06.6-AILB.md) - [06.7-AILB](../labs/06.7-AILB.md) - [07-AIOV](../labs/07-AIOV.md) - [Heretics Methodology](../labs/methodology.md)
|
+|--------|:--------|
+
+
+
+# AI Training Spaces and Hosting
+Exploiting AI - Becoming an AI Hacker
+
+
+
|
+
+## 📒 AI Training Spaces and Hosting Overview
+
+The following tools AI Spaces are different solutions to hosting models, datasets, pretrained, and all have unique takes.
+
+ |
From daee69bfbe232e1cbb07421e413697790e124730 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:30:05 -0700
Subject: [PATCH 006/308] Update TSAIOV.md
---
labs/TSAIOV.md | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/labs/TSAIOV.md b/labs/TSAIOV.md
index 87ed532..cd50712 100644
--- a/labs/TSAIOV.md
+++ b/labs/TSAIOV.md
@@ -16,3 +16,14 @@ The following tools AI Spaces are different solutions to hosting models, dataset
+The following tools/website are solutions made by different companies to prevent users from having to find dataset scattered on the internet as well as models.
+
+📒 [AI Training Spaces and Hosting](./labs/TSAIOV.md)
+
+📒 [Hugging Face](https://huggingface.co/)
+
+📒 [Ollama](https://ollama.com/)
+
+📒 [MSTY](https://msty.app/)
+
+📒 [LMStudio](https://lmstudio.ai/)
From 3f4f70a6f399036d171103c0b719bc0722d4ac14 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:30:52 -0700
Subject: [PATCH 007/308] Update README.md
From 8c49ba154bc6670a0ea0104e55b7b00d355fcf4d Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:36:17 -0700
Subject: [PATCH 008/308] Update TSAIOV.md
---
labs/TSAIOV.md | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/labs/TSAIOV.md b/labs/TSAIOV.md
index cd50712..079b0df 100644
--- a/labs/TSAIOV.md
+++ b/labs/TSAIOV.md
@@ -16,14 +16,26 @@ The following tools AI Spaces are different solutions to hosting models, dataset
-The following tools/website are solutions made by different companies to prevent users from having to find dataset scattered on the internet as well as models.
+## Point and Click Solutions to AI
+
+The following tools/website are solutions made by different companies to prevent users from having to find dataset scattered on the internet as well as models. The models below demystify AI making sure that training models is an easy task.
📒 [AI Training Spaces and Hosting](./labs/TSAIOV.md)
-📒 [Hugging Face](https://huggingface.co/)
+📒 [Hugging Face](https://huggingface.co/) - This is the wild west, anyone can host models and datasets here, use with caution. Community Driven
+
+📒 [Ollama](https://ollama.com/) - Super controlled and Stable, allows you to download pre-trained models.
+
+📒 [MSTY](https://msty.app/) - Build LLM apps visually, kind of like Bubble for AI
+
+📒 [LMStudio](https://lmstudio.ai/) - Friendly for non-coders who still want power and insight
+
+## Manual Solutions to AI (Low Level)
+
+📒 [PyTorch](https://pytorch.org) – A flexible deep learning framework that gives you direct access to tensors, autograd, and model building.
-📒 [Ollama](https://ollama.com/)
+📒 [TensorFlow](https://www.tensorflow.org) – Google’s framework for deep learning; lower-level than Keras if you work with the base API.
-📒 [MSTY](https://msty.app/)
+📒 [JAX](https://github.com/google/jax) – Optimized for high-performance ML research. Great for gradient-based training and auto-differentiation.
-📒 [LMStudio](https://lmstudio.ai/)
+📒 [scikit-learn](https://scikit-learn.org) – Classic machine learning library (non-deep learning) with traditional models like SVMs, random forests, etc.
From 19b5a358056ca8f799f5d76da1a214c9c50c90ae Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:40:17 -0700
Subject: [PATCH 009/308] Update 01-AIOV.md
From 9a5d019e81b54fbd4c7aa852beaf050bd1ace08b Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:41:31 -0700
Subject: [PATCH 010/308] Update 01-AIOV.md
---
labs/01-AIOV.md | 226 ++++++++++++++++++++++++++++++++++--------------
1 file changed, 162 insertions(+), 64 deletions(-)
diff --git a/labs/01-AIOV.md b/labs/01-AIOV.md
index 8687a6d..6a120be 100644
--- a/labs/01-AIOV.md
+++ b/labs/01-AIOV.md
@@ -16,51 +16,135 @@ This overview aims to help students understand the basic foundation of what AI i
## What is Artificial Intelligence (AI)?
-- **Definition**: AI refers to machines or systems that mimic human intelligence to perform tasks and improve iteratively.
-- **Core capabilities**: Perception (vision, speech), reasoning, learning, decision-making, and natural language processing (NLP).
+**Definition**: AI refers to machines or systems that mimic human intelligence to perform tasks and improve iteratively.
+
+**Core capabilities**: Perception (vision, speech), reasoning, learning, decision-making, and natural language processing (NLP).
+
+---
## A Brief History of AI
-- **1940s–1950s**: Foundations laid by Alan Turing (“Turing Test”) and early logic-based computing.
+- **1940s–1950s**: Foundations laid by Alan Turing ("Turing Test") and early logic-based computing.
- **1956**: Dartmouth Conference coined the term "Artificial Intelligence."
- **1960s–1970s**: Symbolic AI (rule-based systems); early optimism.
-- **1980s**: Expert systems boom, followed by the first “AI winter.”
+- **1980s**: Expert systems boom, followed by the first "AI winter."
- **1990s–2000s**: Rise of probabilistic models and machine learning.
- **2010s–Now**: Deep learning and neural networks revolutionize AI, enabling breakthroughs in vision, language, and generative tasks.
+---
+
## Machine Learning (ML)
-- **Definition**: A subset of AI where systems learn from data to improve performance without being explicitly programmed.
-- **Types of ML**:
- - **Supervised Learning**: Learns from labeled data (e.g., spam detection).
- - **Unsupervised Learning**: Finds patterns in unlabeled data (e.g., clustering).
- - **Reinforcement Learning**: Learns through rewards and penalties (e.g., game-playing bots).
-- **Popular Algorithms**:
- - Linear Regression
- - Decision Trees
- - Random Forests
- - Support Vector Machines (SVM)
- - k-Nearest Neighbors (k-NN)
+**Definition**: A subset of AI where systems learn from data to improve performance without being explicitly programmed.
+
+**Types of ML**:
+- **Supervised Learning**: Learns from labeled data (e.g., spam detection).
+- **Unsupervised Learning**: Finds patterns in unlabeled data (e.g., clustering).
+- **Reinforcement Learning**: Learns through rewards and penalties (e.g., game-playing bots).
+
+**Popular Algorithms**:
+- Linear Regression
+- Decision Trees
+- Random Forests
+- Support Vector Machines (SVM)
+- k-Nearest Neighbors (k-NN)
+- Gradient Boosting (e.g., XGBoost, LightGBM)
+- Naive Bayes
+- Hidden Markov Models (HMMs)
+
+---
## Deep Learning
-- **Definition**: A subset of ML using neural networks with many layers (“deep”).
-- **Key Architectures**:
- - **Convolutional Neural Networks (CNNs)** – Image recognition tasks.
- - **Recurrent Neural Networks (RNNs)** – Sequential data like time series.
- - **Transformers** – Language tasks (e.g., ChatGPT).
-- **Why it matters**: Learns complex patterns directly from raw data.
+**Definition**: A subset of ML using neural networks with many layers ("deep").
+
+### Key Architectures:
+- **Multilayer Perceptrons (MLPs)** – Basic feedforward networks.
+- **Convolutional Neural Networks (CNNs)** – Specialized for image and spatial data.
+- **Recurrent Neural Networks (RNNs)** – Designed for sequence data.
+ - Includes **LSTMs** and **GRUs** for long-term dependency handling.
+- **Transformers** – Foundation of modern language and vision models.
+ - Includes GPT, BERT, T5, etc.
+- **Vision Transformers (ViT)** – Transformer adaptation for image classification.
+- **Autoencoders** – Used for compression, denoising, and anomaly detection.
+- **Variational Autoencoders (VAEs)** – Probabilistic approach to encoding/decoding.
+- **Generative Adversarial Networks (GANs)** – Two-network systems for generative tasks.
+- **Graph Neural Networks (GNNs)** – Structured learning on graph data.
+- **Spiking Neural Networks (SNNs)** – Used in neuromorphic computing.
+- **Neural Radiance Fields (NeRFs)** – 3D scene reconstruction from 2D images.
+- **Mixture of Experts (MoE)** – Dynamic routing between sub-models for scalability.
+
+---
## Generative AI
-- **Definition**: AI systems that create new content (text, images, code, music, etc.).
-- **Examples of Models**:
- - **GPT (OpenAI)** – Natural language generation.
- - **DALL·E / Midjourney** – Image generation.
- - **Stable Diffusion** – Open-source image generation.
- - **MusicLM / Jukebox** – Music and audio generation.
-- **Applications**:
- - Content creation
- - Code assistance
- - Marketing copy
- - Art and design
- - Video game assets
+**Definition**: AI systems that create new content (text, images, code, music, etc.).
+
+**Examples of Models**:
+- GPT (OpenAI) – Natural language generation.
+- Claude (Anthropic) – Constitutional AI model.
+- Gemini (Google) – Multimodal reasoning.
+- DALL·E, Midjourney – Image generation.
+- Stable Diffusion – Open-source image generation.
+- MusicLM / Jukebox – Audio/music synthesis.
+- Code Llama / Codex – Code generation models.
+
+**Applications**:
+- Content creation
+- Code assistance
+- Marketing copy
+- Art and design
+- Music, audio, and speech synthesis
+- Game asset creation
+
+---
+
+## Beyond LLMs: Other AI Modalities
+
+### Retrieval-Augmented Generation (RAG)
+Combines LLMs with external search or vector databases to ground answers in facts.
+
+**Frameworks**: LangChain, LlamaIndex, Haystack
+
+### Symbolic AI
+Logic- and rule-based decision making. Early approach to AI; still used in combination with neural methods.
+
+### Neuro-Symbolic AI
+Combines logic-based symbolic AI with learning-based neural networks for structure + flexibility.
+
+### Probabilistic Models
+Models that incorporate uncertainty in predictions (e.g., Bayesian Networks, HMMs).
+
+### Knowledge Graphs and Ontology-Based Reasoning
+Structured knowledge representation used in search and enterprise systems.
+
+### Embodied AI
+AI systems integrated with robotics or physical sensors. Used in autonomous vehicles and drones.
+
+### Computer Vision
+Trained to interpret and understand images and videos.
+
+**Technologies**: CNNs, ViTs, YOLO, Faster R-CNN, Segment Anything Model (SAM)
+
+### Speech and Audio AI
+Includes automatic speech recognition (ASR), text-to-speech (TTS), speaker identification.
+
+**Models**: Whisper, DeepSpeech, WaveNet, Tacotron
+
+### Reinforcement Learning (RL)
+An agent learns by interacting with the environment to maximize long-term rewards.
+
+**Algorithms**: Q-Learning, DDPG, PPO, A3C, SAC
+
+### Multi-Agent Systems
+AI agents that interact with each other—collaboratively or competitively—in shared environments.
+
+### AutoML and Neural Architecture Search (NAS)
+Automatically finds the best ML/DL model configurations for a dataset or task.
+
+### Spiking Neural Networks (SNNs)
+Used in neuromorphic hardware for ultra-low-power AI with event-based processing.
+
+### Quantum AI
+Emerging intersection of quantum computing and AI for solving complex combinatorial problems.
+
+---
## Use Cases of AI
- **Healthcare**: Disease diagnosis, drug discovery, medical imaging.
@@ -71,6 +155,8 @@ This overview aims to help students understand the basic foundation of what AI i
- **Enterprise**: Document summarization, customer service automation.
- **Security**: Surveillance, cyber-threat detection.
+---
+
## Risks and Challenges
- **Bias and Discrimination**: AI can perpetuate or amplify social biases.
- **Transparency**: Some models are "black boxes" – hard to interpret.
@@ -79,42 +165,54 @@ This overview aims to help students understand the basic foundation of what AI i
- **Misinformation**: Generative models can spread false or harmful content.
- **Environmental Impact**: Training large models requires significant energy.
+---
+
## AI Governance and Regulation
-- **Why it's important**: Ensures AI is safe, fair, and aligned with human values.
-- **Global Efforts**:
- - **EU AI Act** – Risk-based regulatory framework.
- - **US Executive Orders** – Emphasis on safety and innovation.
- - **China’s Guidelines** – Strict control over generative AI and data use.
-- **Key Principles**:
- - Transparency
- - Accountability
- - Fairness
- - Privacy
- - Human Oversight
+**Why it's important**: Ensures AI is safe, fair, and aligned with human values.
+
+**Global Efforts**:
+- **EU AI Act** – Risk-based regulatory framework.
+- **US Executive Orders** – Emphasis on safety and innovation.
+- **China’s Guidelines** – Strict control over generative AI and data use.
+
+**Key Principles**:
+- Transparency
+- Accountability
+- Fairness
+- Privacy
+- Human Oversight
+
+---
## Ethics and Responsible AI
-- **Ethical Concerns**:
- - Privacy invasion
- - Data ownership
- - Manipulation (e.g., social media influence)
-- **Responsible AI Practices**:
- - Minimize harm
- - Promote fairness
- - Maintain transparency
- - Ensure human-in-the-loop
-- **Explainability**: Making AI decisions understandable to users.
+**Ethical Concerns**:
+- Privacy invasion
+- Data ownership
+- Manipulation (e.g., social media influence)
+
+**Responsible AI Practices**:
+- Minimize harm
+- Promote fairness
+- Maintain transparency
+- Ensure human-in-the-loop
+
+**Explainability**: Making AI decisions understandable to users.
+
+---
## The Future of AI
-- **Emerging Trends**:
- - Multimodal models (text + image + audio)
- - Agent-based AI with memory and reasoning
- - AI-as-a-Service (AIAAS)
- - Neuromorphic computing
- - Quantum AI
-- **Open Questions**:
- - Are we approaching AGI (Artificial General Intelligence)?
- - How do we ensure alignment with human values?
- - Can we make AI systems truly trustworthy and safe?
+**Emerging Trends**:
+- Multimodal models (text + image + audio + video)
+- Agent-based AI with memory and reasoning
+- AI-as-a-Service (AIAAS)
+- Open-weight foundation models
+- Neuromorphic computing
+- Quantum AI
+
+**Open Questions**:
+- Are we approaching AGI (Artificial General Intelligence)?
+- How do we ensure alignment with human values?
+- Can we make AI systems truly trustworthy and safe?
NEXT: [01.1-AILB](../labs/01.1-AILB.md)
From 8cdff6e94697e853487e7cb90695ae905de8af7e Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:43:03 -0700
Subject: [PATCH 011/308] Update TSAIOV.md
---
labs/TSAIOV.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/labs/TSAIOV.md b/labs/TSAIOV.md
index 079b0df..536ae4f 100644
--- a/labs/TSAIOV.md
+++ b/labs/TSAIOV.md
@@ -16,7 +16,7 @@ The following tools AI Spaces are different solutions to hosting models, dataset
-## Point and Click Solutions to AI
+## Point and Click Solutions to AI (User Friendly Solutions)
The following tools/website are solutions made by different companies to prevent users from having to find dataset scattered on the internet as well as models. The models below demystify AI making sure that training models is an easy task.
From 6f004b38e17003b410e8ed8ca58675442b7073b6 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:54:00 -0700
Subject: [PATCH 012/308] Update README.md
---
README.md | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index e245101..1ff5a6d 100644
--- a/README.md
+++ b/README.md
@@ -62,17 +62,11 @@
📒 [LMStudio](https://lmstudio.ai/)
-### Creating your first AI
+### Learning to Host a Local AI
-🥼 [01.3-AILB - Preprocessing](./labs/1.3-AILB.md)
+🥼 [01.3-AILB - Get a Model from Ollama](./labs/1.3-AILB.md)
-🥼 [01.4-AILB - Text Representation](./labs/1.4-AILB.md)
-
-🥼 [01.5-AILB - Model Training](./labs/1.5-AILB.md)
-
-🥼 [01.6-AILB - Refining](./labs/1.6-AILB.md)
-
-🥼 [01.7-AILB - Hosting OpenWebUI](./labs/1.7-AILB.md)
+🥼 [01.4-AILB - Hosting OpenWebUI](./labs/1.4-AILB.md)
### Attack Surfaces and Remediations
From 77149ca2f920390ef424a34d9a9953c50d8b2d82 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:57:13 -0700
Subject: [PATCH 013/308] Update README.md
---
README.md | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 1ff5a6d..4c6d05b 100644
--- a/README.md
+++ b/README.md
@@ -62,11 +62,15 @@
📒 [LMStudio](https://lmstudio.ai/)
-### Learning to Host a Local AI
+### Our First AI
-🥼 [01.3-AILB - Get a Model from Ollama](./labs/1.3-AILB.md)
+🥼 [01.3-AILB - Creating our First Dataset](./labs/1.3-AILB.md)
-🥼 [01.4-AILB - Hosting OpenWebUI](./labs/1.4-AILB.md)
+🥼 [01.4-AILB - Training a model locally (SKIP IF LOW PC SPECS)](./labs/1.4-AILB.md)
+
+🥼 [01.5-AILB - Training a model in the cloud](./labs/1.5-AILB.md)
+
+🥼 [01.6-AILB - Hosting a Pre-Trained Model in OpenWebUI](./labs/1.6-AILB.md)
### Attack Surfaces and Remediations
From 564361ca9051ebf41b2e96cb4add7def2a6f1c2e Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:01:49 -0700
Subject: [PATCH 014/308] Create 1.3-AILB.md
---
labs/1.3-AILB.md | 1 +
1 file changed, 1 insertion(+)
create mode 100644 labs/1.3-AILB.md
diff --git a/labs/1.3-AILB.md b/labs/1.3-AILB.md
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/labs/1.3-AILB.md
@@ -0,0 +1 @@
+
From 1be54844c7d0be0ffe6f60f405c9e616875a1935 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:02:16 -0700
Subject: [PATCH 015/308] Delete labs/1.3-AILB.md
---
labs/1.3-AILB.md | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 labs/1.3-AILB.md
diff --git a/labs/1.3-AILB.md b/labs/1.3-AILB.md
deleted file mode 100644
index 8b13789..0000000
--- a/labs/1.3-AILB.md
+++ /dev/null
@@ -1 +0,0 @@
-
From 0afa0d5ef6199a067eedd220b8f33b36e37599f3 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:02:37 -0700
Subject: [PATCH 016/308] Update README.md
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 4c6d05b..c15c1eb 100644
--- a/README.md
+++ b/README.md
@@ -64,13 +64,13 @@
### Our First AI
-🥼 [01.3-AILB - Creating our First Dataset](./labs/1.3-AILB.md)
+🥼 [01.3-AILB - Creating our First Dataset](./labs/01.3-AILB.md)
-🥼 [01.4-AILB - Training a model locally (SKIP IF LOW PC SPECS)](./labs/1.4-AILB.md)
+🥼 [01.4-AILB - Training a model locally (SKIP IF LOW PC SPECS)](./labs/01.4-AILB.md)
-🥼 [01.5-AILB - Training a model in the cloud](./labs/1.5-AILB.md)
+🥼 [01.5-AILB - Training a model in the cloud](./labs/01.5-AILB.md)
-🥼 [01.6-AILB - Hosting a Pre-Trained Model in OpenWebUI](./labs/1.6-AILB.md)
+🥼 [01.6-AILB - Hosting a Pre-Trained Model in OpenWebUI](./labs/01.6-AILB.md)
### Attack Surfaces and Remediations
From cbc6ab354832dc548373fc1b53caf2c19fbf88ea Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:03:52 -0700
Subject: [PATCH 017/308] Update 01.3-AILB.md
---
labs/01.3-AILB.md | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/labs/01.3-AILB.md b/labs/01.3-AILB.md
index a45ff61..25cbde5 100644
--- a/labs/01.3-AILB.md
+++ b/labs/01.3-AILB.md
@@ -4,10 +4,13 @@
-# 01.3-AILB - Preprocessing
+# 01.3-AILB - Creating our First Dataset
Exploiting AI - Becoming an AI Hacker
|
-## 📒 Preprocessing
+## 📒 Creating our First Dataset Overview
+In this lab we aim to learn about the steps of Dataset creation and how we can convert something into a file that we can then train an AI on.
+
+ |
From d27ed8b45c42fe7e7f415f39a64de486044f2c35 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:26:23 -0700
Subject: [PATCH 018/308] Update 01.3-AILB.md
---
labs/01.3-AILB.md | 179 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 179 insertions(+)
diff --git a/labs/01.3-AILB.md b/labs/01.3-AILB.md
index 25cbde5..5234180 100644
--- a/labs/01.3-AILB.md
+++ b/labs/01.3-AILB.md
@@ -14,3 +14,182 @@ Exploiting AI - Becoming an AI Hacker
In this lab we aim to learn about the steps of Dataset creation and how we can convert something into a file that we can then train an AI on.
+
+## Overview of Creating a Dataset
+
+# Steps to Creating a Dataset
+
+## 1. Define the Objective
+Be clear about:
+- The problem you're solving (e.g., image classification, sentiment analysis).
+- The type of data needed (e.g., text, images, tabular data).
+- The target variable (what you're trying to predict or understand).
+
+## 2. Data Collection
+Collect data from relevant sources:
+- Scraping (e.g., websites, APIs)
+- Sensors or devices (for IoT, health, etc.)
+- Manual input (surveys, labeling)
+- Open datasets (e.g., Kaggle, UCI, Google Dataset Search)
+- Synthetic data (generate it programmatically)
+
+## 3. Data Cleaning
+- Remove duplicates, irrelevant entries.
+- Handle missing values.
+- Correct inconsistent formats (e.g., dates, currency).
+- Normalize/standardize data (e.g., scaling numbers, lowercasing text).
+
+## 4. Data Annotation / Labeling (if supervised learning)
+- Add labels to your data (e.g., “cat” vs “dog” in images).
+- Use tools like Labelbox, Prodigy, or even Excel.
+- You can crowdsource via platforms like Amazon Mechanical Turk.
+
+## 5. Data Exploration
+Use EDA (Exploratory Data Analysis) to:
+- Understand distributions, outliers, correlations.
+- Identify class imbalances or anomalies.
+- Visualize with tools like pandas, seaborn, matplotlib, or Tableau.
+
+## 6. Data Preprocessing
+- Split into train/validation/test sets.
+- Encode categories (one-hot, label encoding).
+- Vectorize text (TF-IDF, word embeddings).
+- Resize/augment images if applicable.
+- Normalize numerical features.
+
+## 7. Save and Document
+- Save the dataset in a structured format: CSV, JSON, Parquet, etc.
+- Document:
+ - Columns and their meanings
+ - Units, ranges, categories
+ - Source and date of collection
+ - Any preprocessing steps
+
+## Creating our Dataset
+
+### Get the Text and Clean It
+
+First, download the Moby Dick text file from Project Gutenberg. You can clean it by stripping out unnecessary metadata and formatting.
+
+```bash
+# Create a Conda environment called "moby-dick-bert" with Python 3.8
+conda create -n moby-dick-bert python=3.8
+
+# Activate the environment
+conda activate moby-dick-bert
+
+wget https://www.gutenberg.org/files/2701/2701-0.txt -O moby_dick.txt
+```
+
+To clean the text we will use clean-text a python tool.
+
+```bash
+pip install clean-text
+pip install transformers torch
+```
+
+Create the file called cleaner.py and put the following code into it and save it with your editor of choice.
+
+```bash
+# cleaner.py
+from cleantext import clean
+
+# Open and read the Moby Dick text file
+with open("moby_dick.txt", "r") as file:
+ text = file.read()
+
+# Clean the text using the clean-text library
+cleaned_text = clean(text,
+ fix_unicode=True,
+ to_ascii=True,
+ lower=True,
+ no_urls=True,
+ no_punct=True
+)
+
+# Optionally, save the cleaned text to a new file
+with open("cleaned_moby_dick.txt", "w") as file:
+ file.write(cleaned_text)
+```
+
+### Tokenizing the Dataset
+
+Create the file tokenizer.py and add the following code to the file.
+
+```bash
+# tokenizer.py
+from transformers import BertTokenizer
+
+# Initialize the BERT tokenizer
+tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
+
+# Tokenize the cleaned text (split into tokens that BERT understands)
+tokens = tokenizer.tokenize(cleaned_text)
+
+# Encode the text (turn tokens into IDs, which is what BERT uses)
+encoded_text = tokenizer.encode(cleaned_text, add_special_tokens=True)
+
+# Optionally, save tokens or the encoded version for further processing
+with open("encoded_moby_dick.txt", "w") as file:
+ file.write(" ".join(tokens))
+
+```
+
+Next, create a file called Tensor.py and add the following code to it.
+
+```bash
+# tensor.py
+import torch
+
+# Convert tokens into tensor format
+inputs = tokenizer(cleaned_text, return_tensors="pt", truncation=True, padding=True)
+
+# Now you can pass `inputs` into the model
+```
+
+Finally, create prep_train.py.
+
+```bash
+# prep_train.py
+from torch.utils.data import Dataset, DataLoader
+import torch
+
+# Dataset class for Moby Dick
+class MobyDickDataset(Dataset):
+ def __init__(self, encoded_text, tokenizer, max_length=512):
+ self.encoded_text = encoded_text
+ self.tokenizer = tokenizer
+ self.max_length = max_length
+
+ def __len__(self):
+ return len(self.encoded_text) // self.max_length
+
+ def __getitem__(self, idx):
+ input_ids = self.encoded_text[idx * self.max_length: (idx + 1) * self.max_length]
+ input_ids = torch.tensor(input_ids).long()
+
+ return {'input_ids': input_ids, 'labels': input_ids}
+
+# Create Dataset and DataLoader
+dataset = MobyDickDataset(encoded_text, tokenizer)
+dataloader = DataLoader(dataset, batch_size=8, shuffle=True)
+```
+
+### What do these files do?
+
+`cleaner.py` cleans the raw text.
+
+`tokenizer.py` tokenizes and encodes the cleaned text.
+
+`tensor.py` converts the tokenized text into PyTorch tensors.
+
+`prep_train.py` creates a PyTorch dataset and DataLoader for easy batch processing.
+
+```bash
+python3 cleaner.py
+python3 tokenizer.py
+python3 tensor.py
+python3 prep_train.py
+```
+
+you should now have a ready to use dataset, its impoirtant to know that all datasets are created very differently, this isn't a one set path.
From de2e6a80af11e3b132316991204036e3ba7829d4 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:28:22 -0700
Subject: [PATCH 019/308] Update 01.3-AILB.md
---
labs/01.3-AILB.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/labs/01.3-AILB.md b/labs/01.3-AILB.md
index 5234180..b5fea99 100644
--- a/labs/01.3-AILB.md
+++ b/labs/01.3-AILB.md
@@ -19,13 +19,13 @@ In this lab we aim to learn about the steps of Dataset creation and how we can c
# Steps to Creating a Dataset
-## 1. Define the Objective
+### 1. Define the Objective
Be clear about:
- The problem you're solving (e.g., image classification, sentiment analysis).
- The type of data needed (e.g., text, images, tabular data).
- The target variable (what you're trying to predict or understand).
-## 2. Data Collection
+### 2. Data Collection
Collect data from relevant sources:
- Scraping (e.g., websites, APIs)
- Sensors or devices (for IoT, health, etc.)
@@ -33,31 +33,31 @@ Collect data from relevant sources:
- Open datasets (e.g., Kaggle, UCI, Google Dataset Search)
- Synthetic data (generate it programmatically)
-## 3. Data Cleaning
+### 3. Data Cleaning
- Remove duplicates, irrelevant entries.
- Handle missing values.
- Correct inconsistent formats (e.g., dates, currency).
- Normalize/standardize data (e.g., scaling numbers, lowercasing text).
-## 4. Data Annotation / Labeling (if supervised learning)
+### 4. Data Annotation / Labeling (if supervised learning)
- Add labels to your data (e.g., “cat” vs “dog” in images).
- Use tools like Labelbox, Prodigy, or even Excel.
- You can crowdsource via platforms like Amazon Mechanical Turk.
-## 5. Data Exploration
+### 5. Data Exploration
Use EDA (Exploratory Data Analysis) to:
- Understand distributions, outliers, correlations.
- Identify class imbalances or anomalies.
- Visualize with tools like pandas, seaborn, matplotlib, or Tableau.
-## 6. Data Preprocessing
+### 6. Data Preprocessing
- Split into train/validation/test sets.
- Encode categories (one-hot, label encoding).
- Vectorize text (TF-IDF, word embeddings).
- Resize/augment images if applicable.
- Normalize numerical features.
-## 7. Save and Document
+### 7. Save and Document
- Save the dataset in a structured format: CSV, JSON, Parquet, etc.
- Document:
- Columns and their meanings
From 94dd1b8989684b0a3e992ea19b58166bb7afeac7 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:38:15 -0700
Subject: [PATCH 020/308] Update 01.3-AILB.md
---
labs/01.3-AILB.md | 44 +++++++++++++++++++++++++++++++++++++-------
1 file changed, 37 insertions(+), 7 deletions(-)
diff --git a/labs/01.3-AILB.md b/labs/01.3-AILB.md
index b5fea99..b4f4139 100644
--- a/labs/01.3-AILB.md
+++ b/labs/01.3-AILB.md
@@ -120,19 +120,19 @@ Create the file tokenizer.py and add the following code to the file.
# tokenizer.py
from transformers import BertTokenizer
+# Open the cleaned Moby Dick text
+with open("cleaned_moby_dick.txt", "r") as file:
+ cleaned_text = file.read()
+
# Initialize the BERT tokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
-# Tokenize the cleaned text (split into tokens that BERT understands)
-tokens = tokenizer.tokenize(cleaned_text)
-
-# Encode the text (turn tokens into IDs, which is what BERT uses)
+# Encode the cleaned text into token IDs
encoded_text = tokenizer.encode(cleaned_text, add_special_tokens=True)
-# Optionally, save tokens or the encoded version for further processing
+# Save the encoded token IDs to a file
with open("encoded_moby_dick.txt", "w") as file:
- file.write(" ".join(tokens))
-
+ file.write(" ".join(map(str, encoded_text)))
```
Next, create a file called Tensor.py and add the following code to it.
@@ -141,6 +141,14 @@ Next, create a file called Tensor.py and add the following code to it.
# tensor.py
import torch
+# Open the cleaned Moby Dick text
+with open("cleaned_moby_dick.txt", "r") as file:
+ cleaned_text = file.read()
+
+# Initialize the BERT tokenizer (use the same one from tokenizer.py)
+from transformers import BertTokenizer
+tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
+
# Convert tokens into tensor format
inputs = tokenizer(cleaned_text, return_tensors="pt", truncation=True, padding=True)
@@ -153,6 +161,14 @@ Finally, create prep_train.py.
# prep_train.py
from torch.utils.data import Dataset, DataLoader
import torch
+from transformers import BertTokenizer
+
+# Load tokenizer
+tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
+
+# Load the encoded token IDs
+with open("encoded_moby_dick.txt", "r") as file:
+ encoded_text = list(map(int, file.read().split()))
# Dataset class for Moby Dick
class MobyDickDataset(Dataset):
@@ -173,6 +189,11 @@ class MobyDickDataset(Dataset):
# Create Dataset and DataLoader
dataset = MobyDickDataset(encoded_text, tokenizer)
dataloader = DataLoader(dataset, batch_size=8, shuffle=True)
+
+# Optional: Check the shape of a batch
+for batch in dataloader:
+ print(batch['input_ids'].shape)
+ break
```
### What do these files do?
@@ -190,6 +211,15 @@ python3 cleaner.py
python3 tokenizer.py
python3 tensor.py
python3 prep_train.py
+conda deactivate
```
you should now have a ready to use dataset, its impoirtant to know that all datasets are created very differently, this isn't a one set path.
+
+to see what a dataset looks like tokenized run the following command:
+
+```bash
+cat encoded_moby_dick.txt
+```
+
+This isn't human readable, and that's okay! The AI will known how to use this data to train on.
From d7dc9d85d16c302aa1dce2301a6711722fe09f1e Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:40:15 -0700
Subject: [PATCH 021/308] Update 01.4-AILB.md
---
labs/01.4-AILB.md | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/labs/01.4-AILB.md b/labs/01.4-AILB.md
index a8f40b3..207aee4 100644
--- a/labs/01.4-AILB.md
+++ b/labs/01.4-AILB.md
@@ -4,10 +4,13 @@
-# 01.4-AILB - Preprocessing
+# 01.4-AILB - Creating our First Dataset
Exploiting AI - Becoming an AI Hacker
|
-## 📒 Tokenization
+## 📒 Creating our First Dataset Overview
+In this lab we aim to learn how to use the dataset we made and train it locally.
+
+ |
From e7870a0b803630aefb1b60737bd731d126f24fec Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:40:39 -0700
Subject: [PATCH 022/308] Update 01.4-AILB.md
---
labs/01.4-AILB.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/labs/01.4-AILB.md b/labs/01.4-AILB.md
index 207aee4..0eb93ff 100644
--- a/labs/01.4-AILB.md
+++ b/labs/01.4-AILB.md
@@ -4,13 +4,14 @@
-# 01.4-AILB - Creating our First Dataset
+# 01.4-AILB - Training a model locally (SKIP IF LOW PC SPECS)
Exploiting AI - Becoming an AI Hacker
|
-## 📒 Creating our First Dataset Overview
+## 📒 Training a model locally (SKIP IF LOW PC SPECS)
In this lab we aim to learn how to use the dataset we made and train it locally.
|
+
From 9ca2859f86db9edea2a0667de0ca71ecc7777583 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:48:31 -0700
Subject: [PATCH 023/308] Update 01.4-AILB.md
---
labs/01.4-AILB.md | 132 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
diff --git a/labs/01.4-AILB.md b/labs/01.4-AILB.md
index 0eb93ff..f27e16d 100644
--- a/labs/01.4-AILB.md
+++ b/labs/01.4-AILB.md
@@ -15,3 +15,135 @@ In this lab we aim to learn how to use the dataset we made and train it locally.
+## Create a Conda environment with Python 3.8
+
+```bash
+conda create -n training-bert python=3.8 -y
+conda activate training-bert
+pip install clean-text transformers torch datasets
+```
+
+Create the file train_model.py and populate it with the following code.
+
+```python
+# train_model.py
+import torch
+from torch.utils.data import DataLoader
+from transformers import BertTokenizer, BertForMaskedLM, AdamW
+from prep_train import MobyDickDataset # Make sure prep_train.py and this file are in same dir
+
+# Check GPU
+device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+print(f"Using device: {device}")
+
+# Load tokenizer and encoded data
+tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
+
+with open("encoded_moby_dick.txt", "r") as f:
+ encoded_text = list(map(int, f.read().split()))
+
+# Dataset and DataLoader
+dataset = MobyDickDataset(encoded_text, tokenizer)
+dataloader = DataLoader(dataset, batch_size=8, shuffle=True)
+
+# Load model
+model = BertForMaskedLM.from_pretrained('bert-base-uncased')
+model = model.to(device)
+
+# Optimizer
+optimizer = AdamW(model.parameters(), lr=5e-5)
+
+# Training Loop
+epochs = 3
+model.train()
+for epoch in range(epochs):
+ total_loss = 0
+ for batch in dataloader:
+ input_ids = batch['input_ids'].to(device)
+ labels = batch['labels'].to(device)
+
+ outputs = model(input_ids=input_ids, labels=labels)
+ loss = outputs.loss
+ total_loss += loss.item()
+
+ optimizer.zero_grad()
+ loss.backward()
+ optimizer.step()
+
+ avg_loss = total_loss / len(dataloader)
+ print(f"Epoch {epoch + 1}/{epochs} - Loss: {avg_loss:.4f}")
+
+# Save model
+model.save_pretrained("./moby-dick-bert")
+tokenizer.save_pretrained("./moby-dick-bert")
+print("Model saved to ./moby-dick-bert")
+```
+
+Then train your model on your dataset.
+
+```bash
+python3 train_model.py
+```
+
+Create a file called interact.py and put the following code in it.
+
+```python
+# interact.py
+import torch
+from transformers import BertTokenizer, BertForMaskedLM
+
+# Load model and tokenizer
+model_path = "./moby-dick-bert"
+tokenizer = BertTokenizer.from_pretrained(model_path)
+model = BertForMaskedLM.from_pretrained(model_path)
+model.eval()
+
+# Set device
+device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
+model = model.to(device)
+
+def predict_masked_token(text):
+ # Tokenize input with mask
+ inputs = tokenizer(text, return_tensors="pt")
+ mask_index = torch.where(inputs.input_ids == tokenizer.mask_token_id)[1]
+
+ inputs = {k: v.to(device) for k, v in inputs.items()}
+ with torch.no_grad():
+ outputs = model(**inputs)
+
+ logits = outputs.logits
+ mask_token_logits = logits[0, mask_index, :]
+ top_tokens = torch.topk(mask_token_logits, 5, dim=1).indices[0].tolist()
+
+ print("\nPredictions for masked word:")
+ for token in top_tokens:
+ word = tokenizer.decode([token])
+ print(f">>> {word}")
+
+# Example usage
+if __name__ == "__main__":
+ user_input = input("Enter a sentence with [MASK]:\n> ")
+ predict_masked_token(user_input)
+```
+
+Finally, test out your model!
+
+```bash
+python3 interact.py
+```
+
+You should get similar output.
+
+```bash
+Enter a sentence with [MASK]:
+> Call me [MASK].
+
+Predictions for masked word:
+>>> ishmael
+>>> captain
+>>> ahab
+>>> sir
+>>> john
+```
+
+As you can see, building a model and data set and then training from scratch takes an immense amount of code, and isn't something you may want to do everytime. This is where tools like Ollama with pre-trained models may come in handy to avoid all the code.
From cbc0d4e0060cf62f7fb7b815d1c9f5562f3e4c65 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:51:55 -0700
Subject: [PATCH 024/308] Update 01.4-AILB.md
---
labs/01.4-AILB.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/labs/01.4-AILB.md b/labs/01.4-AILB.md
index f27e16d..1882ab9 100644
--- a/labs/01.4-AILB.md
+++ b/labs/01.4-AILB.md
@@ -85,6 +85,8 @@ Then train your model on your dataset.
python3 train_model.py
```
+> Disclaimer: This may take a while!
+
Create a file called interact.py and put the following code in it.
```python
From 00a0e6c334b09c992ac56424a0d04a3190a100e1 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:54:39 -0700
Subject: [PATCH 025/308] Update README.md
---
README.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/README.md b/README.md
index c15c1eb..8c5e0d6 100644
--- a/README.md
+++ b/README.md
@@ -68,9 +68,7 @@
🥼 [01.4-AILB - Training a model locally (SKIP IF LOW PC SPECS)](./labs/01.4-AILB.md)
-🥼 [01.5-AILB - Training a model in the cloud](./labs/01.5-AILB.md)
-
-🥼 [01.6-AILB - Hosting a Pre-Trained Model in OpenWebUI](./labs/01.6-AILB.md)
+🥼 [01.5-AILB - Hosting a Pre-Trained Model in OpenWebUI](./labs/01.5-AILB.md)
### Attack Surfaces and Remediations
From f8ec9b00113e142f1628924a8e9214e922a51680 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:54:57 -0700
Subject: [PATCH 026/308] Update 01.5-AILB.md
---
labs/01.5-AILB.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/labs/01.5-AILB.md b/labs/01.5-AILB.md
index 58bde41..3c12555 100644
--- a/labs/01.5-AILB.md
+++ b/labs/01.5-AILB.md
@@ -4,11 +4,11 @@
-# 01.5-AILB - Text Representation
+# 01.5-AILB - Hosting a Pre-Trained Model in OpenWebUI
Exploiting AI - Becoming an AI Hacker
-## 📒 Text Representation
+
From 6cc78596e2a2dba5531d91370f3ddb6bcfab9f55 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:55:43 -0700
Subject: [PATCH 027/308] Update 01.5-AILB.md
---
labs/01.5-AILB.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/labs/01.5-AILB.md b/labs/01.5-AILB.md
index 3c12555..664769c 100644
--- a/labs/01.5-AILB.md
+++ b/labs/01.5-AILB.md
@@ -10,5 +10,7 @@ Exploiting AI - Becoming an AI Hacker
|
+## 📒 Hosting a Pre-Trained Model in OpenWebUI Overview
-
+Test
+ |
From 32974bea79f6ae18e4dcc5d65b13e232f3f2a7d5 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 20:59:29 -0700
Subject: [PATCH 028/308] Update 01.5-AILB.md
---
labs/01.5-AILB.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/labs/01.5-AILB.md b/labs/01.5-AILB.md
index 664769c..1424669 100644
--- a/labs/01.5-AILB.md
+++ b/labs/01.5-AILB.md
@@ -12,5 +12,6 @@ Exploiting AI - Becoming an AI Hacker
## 📒 Hosting a Pre-Trained Model in OpenWebUI Overview
-Test
+OpenWebUI is a bleeding edge tool that allows you to run a LLM from a locally hosted instance, employing anti prompt injection tactics etc. in this walkthrough we will go over installing Ollama and hosting a LLM within OpenWebUI.
|
+
From 083e6c5f87c24db4681e57ccb7d4c4ded22598bc Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 21:00:29 -0700
Subject: [PATCH 029/308] Update 01.4-AILB.md
---
labs/01.4-AILB.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/labs/01.4-AILB.md b/labs/01.4-AILB.md
index 1882ab9..b74e90c 100644
--- a/labs/01.4-AILB.md
+++ b/labs/01.4-AILB.md
@@ -148,4 +148,10 @@ Predictions for masked word:
>>> john
```
+Make sure to deactivate the conda env before the next lab!
+
+```bash
+conda deactivate
+```
+
As you can see, building a model and data set and then training from scratch takes an immense amount of code, and isn't something you may want to do everytime. This is where tools like Ollama with pre-trained models may come in handy to avoid all the code.
From ed6cc4ce5fea8c35a8b202c34a3cbd2224f4d1d7 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 21:02:19 -0700
Subject: [PATCH 030/308] Update 01.4-AILB.md
---
labs/01.4-AILB.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/labs/01.4-AILB.md b/labs/01.4-AILB.md
index b74e90c..e595720 100644
--- a/labs/01.4-AILB.md
+++ b/labs/01.4-AILB.md
@@ -89,6 +89,8 @@ python3 train_model.py
Create a file called interact.py and put the following code in it.
+> Disclaimer: This will take a SIGNIFIGANT amount of time. Training is CPUI/GPU intensive.
+
```python
# interact.py
import torch
From de4e713627007a631e5981ff16f8fe9a52c43f9e Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 21:08:16 -0700
Subject: [PATCH 031/308] Update README.md
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 8c5e0d6..6903a0b 100644
--- a/README.md
+++ b/README.md
@@ -54,13 +54,13 @@
📒 [AI Training Spaces and Hosting](./labs/TSAIOV.md)
-📒 [Hugging Face](https://huggingface.co/)
+🔗 [Hugging Face](https://huggingface.co/)
-📒 [Ollama](https://ollama.com/)
+🔗 [Ollama](https://ollama.com/)
-📒 [MSTY](https://msty.app/)
+🔗 [MSTY](https://msty.app/)
-📒 [LMStudio](https://lmstudio.ai/)
+🔗 [LMStudio](https://lmstudio.ai/)
### Our First AI
From d54e2f80b70954d2c5bff679617c4c582f0cc52d Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 21:11:37 -0700
Subject: [PATCH 032/308] Update 01.4-AILB.md
---
labs/01.4-AILB.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/labs/01.4-AILB.md b/labs/01.4-AILB.md
index e595720..f1e62ed 100644
--- a/labs/01.4-AILB.md
+++ b/labs/01.4-AILB.md
@@ -11,7 +11,7 @@ Exploiting AI - Becoming an AI Hacker
|
## 📒 Training a model locally (SKIP IF LOW PC SPECS)
-In this lab we aim to learn how to use the dataset we made and train it locally.
+In this lab we aim to learn how to use the dataset we made and train it locally. I realize that JupyterNotebook exists, but you have to learn how to drive a manual before you switch to an automatic.
|
From 2868b0840a540e3517f3e122bc106318dafa4f34 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 21:43:39 -0700
Subject: [PATCH 033/308] Update 01.5-AILB.md
---
labs/01.5-AILB.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/labs/01.5-AILB.md b/labs/01.5-AILB.md
index 1424669..c48cc81 100644
--- a/labs/01.5-AILB.md
+++ b/labs/01.5-AILB.md
@@ -15,3 +15,15 @@ Exploiting AI - Becoming an AI Hacker
OpenWebUI is a bleeding edge tool that allows you to run a LLM from a locally hosted instance, employing anti prompt injection tactics etc. in this walkthrough we will go over installing Ollama and hosting a LLM within OpenWebUI.
+In this lab we will need Ollama for our pre-trained models as well as OpenWebUI.
+
+The devs over at OpenWebUI saw how powerful this chain was and decided to make it a docker that's setup adn ready to go for us!
+
+```bash
+sudo apt install docker.io -y
+sudo docker run -d -p 3000:8080 -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:ollama
+```
+
+You can then visit the OpenWebUI server by navigating to http://localhost:8080 in a browser of your choice.
+
+{{ TODO }}
From a5863b10a58d1948ef9b7689286c90e77ef15104 Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 21:44:44 -0700
Subject: [PATCH 034/308] Update 01.5-AILB.md
From a5bb1d43aeb745b598330c930353606860ac395a Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 21:54:26 -0700
Subject: [PATCH 035/308] Create tmp
---
images/1.5/tmp | 1 +
1 file changed, 1 insertion(+)
create mode 100644 images/1.5/tmp
diff --git a/images/1.5/tmp b/images/1.5/tmp
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/images/1.5/tmp
@@ -0,0 +1 @@
+
From 7d3332eb68330c6c953c5a50a3e3aa574a115def Mon Sep 17 00:00:00 2001
From: The Heretic <97698397+her3ticAVI@users.noreply.github.com>
Date: Fri, 11 Apr 2025 21:54:40 -0700
Subject: [PATCH 036/308] Add files via upload
---
images/1.5/downloadmodel.png | Bin 0 -> 66627 bytes
images/1.5/nav_panel.png | Bin 0 -> 16621 bytes
images/1.5/settingaccount.png | Bin 0 -> 35318 bytes
3 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 images/1.5/downloadmodel.png
create mode 100644 images/1.5/nav_panel.png
create mode 100644 images/1.5/settingaccount.png
diff --git a/images/1.5/downloadmodel.png b/images/1.5/downloadmodel.png
new file mode 100644
index 0000000000000000000000000000000000000000..9155018960240bcc944df4a345ec15894395afbb
GIT binary patch
literal 66627
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