EnterpriseQualityCoding / FizzBuzzEnterpriseEdition

FizzBuzz Enterprise Edition is a no-nonsense implementation of FizzBuzz made by serious businessmen for serious business purposes.
21.71k stars 762 forks source link

AI, Vectors, Embeddings, and the Future of FizzBuzz #691

Open nickinnon opened 6 months ago

nickinnon commented 6 months ago

Dear Esteemed Maintainers,

In light of the rapid advancements in artificial intelligence, vector embeddings, and the general future of computational paradigms, I believe it is time to rethink and revolutionize our beloved FizzBuzz algorithm.

As we move towards a world where AI-driven decision-making becomes the norm, it is imperative that our FizzBuzz implementation keeps up with these technological advancements. Below are some proposed enhancements to bring FizzBuzz into the 22nd century:

  1. AI Integration: Implement a deep learning model trained on a vast dataset of integers and their FizzBuzz outputs. This will not only ensure that the AI can predict FizzBuzz results with 99.999% accuracy but also provide a neural network-based approach to handle edge cases like negative numbers and non-integer inputs.
  2. Vector Embeddings: Utilize vector embeddings for numbers to create a high-dimensional space where the relationships between integers can be more intuitively understood. By embedding numbers into a 1024-dimensional space, we can leverage cosine similarity to determine if a number is "Fizz", "Buzz", or "FizzBuzz".
  3. Natural Language Processing (NLP): Employ NLP techniques to interpret user inputs and generate FizzBuzz outputs in various human languages. This can also include sentiment analysis to determine how users feel about specific FizzBuzz results.
  4. Augmented Reality (AR): Create an AR application where users can visualize FizzBuzz results in real-time within their physical environment. This could be particularly useful for educational purposes, allowing students to see "Fizz" and "Buzz" floating around them.

I am confident that these enhancements will propel our FizzBuzz implementation into a new era of technological supremacy and ensure that it remains relevant in the ever-evolving landscape of computational innovations.

Thank you for considering these forward-thinking proposals. I eagerly await your thoughts and the inevitable PRs that will follow.

Best regards,

A Visionary Developer

CodeByAidan commented 5 months ago

Was able to implement the AI integration using a neural network and was able to determine the model accuracy is about 100%, with only a model loss of 0.000099275574%. Includes a test as well, and the TensorFlow model. I wasn't able to finish the NLP or AR part, sorry... Please don't fire me, I'm only a freshman in college... 😞

https://gist.github.com/CodeByAidan/3b0b9d0f83396c8fb042f9c3a0eb5588 (includes model in the gist)

fizzbuzzAI.py

import os
from typing import Any, List, Literal, Union

from matplotlib.pylab import Generator
import numpy as np
import tensorflow as tf
from sklearn.preprocessing import LabelEncoder
from tensorflow.keras.layers import Dense, Embedding, Flatten
from tensorflow.keras.models import Sequential
from word2number import w2n

# Data preparation
def preprocess_input(x: Union[int, float]) -> int:
    return abs(int(x))

data: np.ndarray = np.abs(np.arange(-1000, 1001))
labels: np.ndarray = np.where(
    data % 15 == 0,
    "FizzBuzz",
    np.where(data % 3 == 0, "Fizz", np.where(data % 5 == 0, "Buzz", data.astype(str))),
)

# Encode labels
label_encoder: LabelEncoder = LabelEncoder()
integer_encoded: np.ndarray = label_encoder.fit_transform(labels)
onehot_encoded: np.ndarray = tf.keras.utils.to_categorical(integer_encoded)

# Model setup
model: Sequential = Sequential(
    [
        Embedding(input_dim=2001, output_dim=1024),
        Flatten(),
        Dense(1024, activation="relu"),
        Dense(len(label_encoder.classes_), activation="softmax"),
    ]
)

model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])
model_path = "fizzbuzzAI.h5"
if os.path.isfile(model_path):
    model: Sequential = tf.keras.models.load_model(model_path)
else:
    model.fit(data, onehot_encoded, epochs=50, batch_size=32)
    model.save(model_path)

def process_input(
    user_input: str,
) -> str | Literal["Invalid input, please enter a number."]:
    try:
        num: int = int(w2n.word_to_num(user_input))
        pred: np.ndarray = model.predict(np.array([preprocess_input(num)]))
        return label_encoder.inverse_transform([np.argmax(pred)])[0]
    except ValueError:
        return "Invalid input, please enter a number."

if __name__ == "__main__":
    loss, accuracy = model.evaluate(data, onehot_encoded, verbose=0)

    print(f"Model accuracy: {accuracy*100:.12f}%")
    print(f"Model loss: {loss:.12f}")
    rng: Generator = np.random.default_rng(seed=np.random.SeedSequence(1234))

    for _ in range(10):
        random_input: np.ndarray[Any, np.dtype[Any]] = np.array(
            [rng.integers(-1000, 1001)]
        )
        preprocessed_input: np.ndarray[Any, np.dtype[Any]] = np.array([preprocess_input(random_input[0])])
        predictions = model.predict(preprocessed_input)

        predicted_label = label_encoder.inverse_transform([np.argmax(predictions)])[0]
        print(f"Input: {random_input[0]} | Prediction: {predicted_label}")

test_fizzbuzzAI.py

from typing import Literal

import numpy as np
import pytest
from fizzbuzzAI import label_encoder, model, preprocess_input, process_input

@pytest.mark.parametrize(
    "input_value, expected_output",
    [
        (0, 0),
        (1, 1),
        (-1, 1),
        (1000, 1000),
        (-1000, 1000),
    ],
    ids=[
        "zero",
        "positive_one",
        "negative_one",
        "positive_boundary",
        "negative_boundary",
    ],
)
def test_preprocess_input(
    input_value: Literal[0] | Literal[1] | Literal[-1] | Literal[1000] | Literal[-1000],
    expected_output: Literal[0] | Literal[1] | Literal[1000],
) -> None:
    result: int = preprocess_input(input_value)
    assert result == expected_output

@pytest.mark.parametrize(
    "user_input, expected_output",
    [
        ("zero", "FizzBuzz"),
        ("one", "1"),
        ("three", "Fizz"),
        ("five", "Buzz"),
        ("fifteen", "FizzBuzz"),
        ("negative fifteen", "FizzBuzz"),
        ("negative one", "1"),
        ("one thousand", "Buzz"),
        ("invalid input", "Invalid input, please enter a number."),
    ],
    ids=[
        "zero",
        "one",
        "three",
        "five",
        "fifteen",
        "negative_fifteen",
        "negative_one",
        "one_thousand",
        "invalid_input",
    ],
)
def test_process_input(
    user_input: (
        Literal["zero"]
        | Literal["one"]
        | Literal["three"]
        | Literal["five"]
        | Literal["fifteen"]
        | Literal["negative fifteen"]
        | Literal["negative one"]
        | Literal["one thousand"]
        | Literal["invalid input"]
    ),
    expected_output: (
        Literal["FizzBuzz"]
        | Literal["1"]
        | Literal["Fizz"]
        | Literal["Buzz"]
        | Literal["Invalid input, please enter a number."]
    ),
) -> None:
    result: str = process_input(user_input)
    assert result == expected_output

@pytest.mark.parametrize(
    "data, expected_shape",
    [
        (np.array([0]), (1, 536)),
        (np.array([1, 2, 3]), (3, 536)),
    ],
    ids=[
        "single_input",
        "multiple_inputs",
    ],
)
def test_model_prediction_shape(
    data: np.ndarray,
    expected_shape: tuple[Literal[1], Literal[536]] | tuple[Literal[3], Literal[536]],
) -> None:
    preprocessed_data: np.ndarray = np.array([preprocess_input(x) for x in data])
    predictions = model.predict(preprocessed_data)
    assert predictions.shape == expected_shape

@pytest.mark.parametrize(
    "data, expected_output",
    [
        (np.array([0]), "FizzBuzz"),
        (np.array([1]), "1"),
        (np.array([3]), "Fizz"),
        (np.array([5]), "Buzz"),
        (np.array([15]), "FizzBuzz"),
    ],
    ids=[
        "zero",
        "one",
        "three",
        "five",
        "fifteen",
    ],
)
def test_model_prediction_output(
    data: np.ndarray,
    expected_output: (
        Literal["FizzBuzz"] | Literal["1"] | Literal["Fizz"] | Literal["Buzz"]
    ),
) -> None:
    preprocessed_data: np.ndarray = np.array([preprocess_input(x) for x in data])
    predictions = model.predict(preprocessed_data)
    predicted_label = label_encoder.inverse_transform([np.argmax(predictions)])[0]
    assert predicted_label == expected_output

if __name__ == "__main__":
    pytest.main(["-v", "test_fizzbuzzAI.py"])
tori4582 commented 4 months ago

Hi @CodeByAidan, thanks for your dedicated effort. However, don't forget to attach the JIRA card (with reasonable, proper story points) to your message so that POs could have a better insight of your effort on Burn-out Chart.