def add(
      self,
      text: str,
      *,
      timestamp: datetime.datetime | None = None,
      tags: Iterable[str] = (),
      importance: float | None = None,
  ) -> None:
    """Adds nonduplicated entries (time, text, tags, importance) to the memory.

    Args:
      text: what goes into the memory
      timestamp: the time of the memory
      tags: optional tags
      importance: optionally set the importance of the memory.
    """
    if importance is None:
      with self._memory_bank_lock:
        memory_size = len(self._memory_bank)
      num_to_retrieve = self._num_to_retrieve_to_contextualize_importance
      if memory_size < num_to_retrieve:
        num_to_retrieve = memory_size
      context = self.retrieve_random_with_importance(k=num_to_retrieve)
      importance = self._importance(text, context)

    if timestamp is None:
      timestamp = self._clock_now()

    _check_date_in_range(timestamp)

    # Remove all newline characters from memories.
    text = text.replace('\n', ' ')

    contents = {
        'text': text,
        'time': timestamp,
        'tags': tuple(tags),
        'importance': importance,
    }
    hashed_contents = hash(tuple(contents.values()))
    derived = {'embedding': self._embedder(text)}
    new_df = pd.Series(contents | derived).to_frame().T.infer_objects()

    with self._memory_bank_lock:
      if hashed_contents in self._stored_hashes:
        return
      self._memory_bank = pd.concat(
          [self._memory_bank, new_df], ignore_index=True
      )
      self._stored_hashes.add(hashed_contents)
Adds nonduplicated entries (time, text, tags, importance) to the memory.

    Args:
      text: what goes into the memory
      timestamp: the time of the memory
      tags: optional tags
      importance: optionally set the importance of the memory.
    
concordia/associative_memory/deprecated/associative_memory.py