input: 
  from typing import List, Dict
  import numpy as np
  import pandas as pd
  import nltk
  from nltk.tokenize import word_tokenize
  import matplotlib.pyplot as plt
  from nltk.corpus import stopwords
  from nltk.stem import WordNetLemmatizer 
  from sklearn.feature_extraction.text import CountVectorizer
  from sklearn.model_selection import train_test_split
  from sklearn.naive_bayes import MultinomialNB
  from sklearn.metrics import classification_report
  
  def sentiment_analysis(reviews: List[str], sentiments: List[str]) -> Dict[str, str]:
      """ Perform sentiment analysis on a list of product reviews using natural language 
      processing techniques like tokenization, stopword removal, and lemmatization, and 
      then use a classification model to assign sentiments to the reviews. Returns a 
      dictionary where keys are review texts and values are their assigned sentiments.
      
      >>> sentiment_analysis(['Great product!', 'Not happy with the purchase'], ['positive', 'negative'])
      {'Great product!': 'positive', 'Not happy with the purchase': 'negative'}
      """
      data = pd.DataFrame({'review': reviews, 'sentiment': sentiments})
      data['tokenised'] = data['review'].apply(word_tokenize)
      stop_words = set(stopwords.words('english'))
      data['filtered'] = data['tokenised'].apply(lambda x: [val for val in x if val not in stop_words])
      wordnet_lemmatizer = WordNetLemmatizer()
      data['normalised'] = data['filtered'].apply(lambda x: [wordnet_lemmatizer.lemmatize(val) for val in x])
      cv = CountVectorizer()
      data['features'] = cv.fit_transform(data['normalised'].astype('str')).toarray()
      X = data['features']
      y = data['sentiment']
      X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
      model = MultinomialNB(alpha=0.1)
      model.fit(X_train, y_train)
      predictions = model.predict(X_test)
      report = classification_report(y_test, predictions)
      review_sentiment_dict = dict(zip(X_test, predictions))
      return review_sentiment_dict
  
output:     review_sentiment_dict = {}
      for review in reviews:
          tokenized = word_tokenize(review)
          filtered = [val for val in tokenized if val not in stop_words]
          normalised = [wordnet_lemmatizer.lemmatize(val) for val in filtered]
          feature = cv.transform([' '.join(normalised)]).toarray()
          sentiment = model.predict(feature)[0]
          review_sentiment_dict[review] = sentiment
      return review_sentiment_dict