You can either use the validation loss or accuracy to determine the early stopping. Its better to do it on the epoch validation loss. In the validate function, you can keep track of the running loss and compute the epoch loss outside of the loop. In addition, save the best validation loss (initialized with a very large value) and introduce a patience variable (initialized with 0). Both can be global variables or passed as an argument to the validate function:
def validate(val_loader, model, criterion, num_classes, args):
    running_loss = 0.0
    for i, (images, target) in enumerate(val_loader):
        running_loss += loss.item() * images.size(0)
    epoch_val_loss = running_loss / len(val_loader)
    if epoch_val_loss < best_val_loss:
        best_val_loss = epoch_val_loss
        patience = 0 # reset patience if the loss improved
    else:
        patience += 1 # increase patience counter

    if patience == patience_threshold: # loss didn't decrease for 'patience_threshold' epochs
        return early_stopping # can be a flag to indicate early stopping and break out of the epoch loop

You can do it similarly using the accuracy metric. This is a very crude way to do early stopping. There can be more formal ways and modifications. Feel free to change it according to your needs.