Repository: deepset-ai/haystack

Issue:
Document store `update_embeddings` fails with DPR
**Describe the bug**
If you train a `DensePassageRetriever` with `num_hard_negatives` > 0, then doing the following:

```python
retriever = DensePassageRetriever(
    document_store=InMemoryDocumentStore(),
    query_embedding_model=query_model,
    passage_embedding_model=passage_model,
    max_seq_len_query=128,
    max_seq_len_passage=256,
)

retriever.train(
    data_dir=DATA_PATH,
    train_filename=train_filename,
    dev_filename=val_filename,
    test_filename=val_filename,
    n_epochs=4,
    batch_size=16,
    grad_acc_steps=8,
    save_dir=dpr_model_dir,
    evaluate_every=3000,
    embed_title=False,
    num_positives=1,
    num_hard_negatives=5,

document_store = FAISSDocumentStore(similarity="dot_product")

docs = [] # insert docs here

document_store.write_documents(docs)

document_store.update_embeddings(retriever)
```

will trigger this assert: https://github.com/deepset-ai/haystack/blob/c5138655660b047d37e6628115af1315ca5c782e/haystack/document_store/faiss.py#L261


**Error message**
```python
In [55]: document_store.update_embeddings(retriever)
07/26/2021 15:39:22 - INFO - haystack.document_store.faiss -   Updating embeddings for 100467 docs...
Updating Embedding:   0%|                                                                                                                                                                                                              | 0/100467 [05:09<?, ? docs/s]
---------------------------------------------------------------------------                                                                                                                                                                                          
AssertionError                            Traceback (most recent call last)
<ipython-input-55-a042bbe71db2> in <module>
----> 1 document_store.update_embeddings(retriever)

~/miniconda3/envs/pytorch/lib/python3.7/site-packages/haystack/document_store/faiss.py in update_embeddings(self, retriever, index, update_existing_embeddings, filters, batch_size)
    259             for document_batch in batched_documents:
    260                 embeddings = retriever.embed_passages(document_batch)  # type: ignore
--> 261                 assert len(document_batch) == len(embeddings)
    262 
    263                 embeddings_to_index = np.array(embeddings, dtype="float32")

AssertionError: 
```




Discussion:
By the way, if you load the retriever from disk after training it works fine:

```python
retriever = DensePassageRetriever.load(dpr_model_dir, document_store)

document_store.update_embeddings(retriever)
```

Seems like the issue is actually using the instance that was trained.
Hi @sergeyf , thanks for reporting the issue! This is something we'll be looking in to. Just wondering if this is blocking your task or whether the work around you found is enough for what you're trying to achieve?
Howdy. The workaround is working just fine! Thanks.
@sergeyf Can you please try this code? Mainly I changed the initial document store to retriever from InMemoryDocumentStore to FAISSDocumentStore

```
document_store = FAISSDocumentStore(similarity="dot_product")

retriever = DensePassageRetriever(
    document_store=document_store,
    query_embedding_model=query_model,
    passage_embedding_model=passage_model,
    max_seq_len_query=128,
    max_seq_len_passage=256,
)

retriever.train(
    data_dir=DATA_PATH,
    train_filename=train_filename,
    dev_filename=val_filename,
    test_filename=val_filename,
    n_epochs=4,
    batch_size=16,
    grad_acc_steps=8,
    save_dir=dpr_model_dir,
    evaluate_every=3000,
    embed_title=False,
    num_positives=1,
    num_hard_negatives=5,


docs = [] # insert docs here

document_store.write_documents(docs)

document_store.update_embeddings(retriever)

```
I tried it and it's still got the same issue. I think the issue is related to `num_hard_negatives` because when I set that to 5, the actual number of embeddings that's produced is 6x what it should: 1 for the positive and 5 for each of the negatives. When `num_hard_negatives` was set to 1, the number of embeddings produced was 2x.

Resolving patch:
diff --git a/haystack/retriever/dense.py b/haystack/retriever/dense.py
--- a/haystack/retriever/dense.py
+++ b/haystack/retriever/dense.py
@@ -269,6 +269,12 @@ def embed_passages(self, docs: List[Document]) -> List[np.ndarray]:
         :param docs: List of Document objects used to represent documents / passages in a standardized way within Haystack.
         :return: Embeddings of documents / passages shape (batch_size, embedding_dim)
         """
+
+        if self.processor.num_hard_negatives != 0:
+            logger.warning(f"'num_hard_negatives' is set to {self.processor.num_hard_negatives}, but inference does "
+                           f"not require any hard negatives. Setting num_hard_negatives to 0.")
+            self.processor.num_hard_negatives = 0
+
         passages = [{'passages': [{
             "title": d.meta["name"] if d.meta and "name" in d.meta else "",
             "text": d.text,


Test patch: