如何使用 Sentence Transformers 将元数据用于文档检索?
How to use metadata for document retrieval using Sentence Transformers?
我正在尝试使用 Sentence Transformers 和 Haystack 进行文档检索,重点是在文档文本之外的其他元数据上搜索文档。
我正在使用学术出版物标题的数据集,并且附加了一个虚假的出版年份(我想将其用作搜索词)。通过四处阅读,我合并了各列,并在标题和出版年份之间添加了一个分隔符,并包含了列标题,因为我认为这可能会增加上下文。输入示例如下:
title Sparsity-certifying Graph Decompositions [SEP] published year 1980
我这里有一个文档存储和检索方法,基于this:
document_store_faiss = FAISSDocumentStore(faiss_index_factory_str="Flat",
return_embedding=True,
similarity='cosine')
retriever_faiss = EmbeddingRetriever(document_store_faiss,
embedding_model='all-mpnet-base-v2',
model_format='sentence_transformers')
document_store_faiss.write_documents(df.rename(columns={'combined':'content'}).to_dict(orient='records'))
document_store_faiss.update_embeddings(retriever=retriever_faiss)
def get_results(query, retriever, n_docs = 25):
return [(item.content) for item in retriever.retrieve(q, top_k = n_docs)]
q = 'published year 1999'
print('Results: ')
res = get_results(q, retriever_faiss)
for r in res:
print(r)
我检查是否有任何输入实际上具有与搜索词匹配的出版年份,但是当我查看我的搜索结果时,我得到的条目似乎是随机出版年份。我希望至少所有的结果都是相同的出版年份,因为我希望做更复杂的查询,比如 "published year before 1980".
如果有人能告诉我我做错了什么,或者我是否误解了这个过程/预期结果,我们将不胜感激。
听起来您需要元数据过滤而不是将年份放在查询本身中。 FaissDocumentStore
不支持过滤,我建议切换到几天前 Haystack 在 v1.3 版本中引入的 PineconeDocumentStore
。支持当前文档存储集中最强的过滤功能
您需要确保安装了最新版本的 Haystack,它还需要一个额外的 pinecone-client
库:
pip install -U farm-haystack pinecone-client
有一个 guide here 可能会有帮助,它会是这样的:
document_store = PineconeDocumentStore(
api_key="<API_KEY>", # from https://app.pinecone.io
environment="us-west1-gcp"
)
retriever = EmbeddingRetriever(
document_store,
embedding_model='all-mpnet-base-v2',
model_format='sentence_transformers'
)
在编写文档之前,您需要转换数据以在 content
中包含您的文本(正如您在上面所做的那样,但不需要 pre-append 年份),然后包含年份作为 meta
字典中的一个字段。因此,您将创建一个字典列表,如下所示:
dicts = [
{'content': 'your text here', 'meta': {'year': 1999}},
{'content': 'another record text', 'meta': {'year': 1971}},
...
]
我不知道你的 df
的确切格式,但假设它是这样的:
text
year
"your text here"
1999
"another record here"
1971
我们可以编写以下代码来重新格式化它:
df = df.rename(columns={'text': 'content'}) # you did this already
# create a new 'meta' column that contains {'year': <year>} data
df['meta'] = df['year'].apply(lambda x: {'year': x})
# we don't need the year column anymore so we drop it
df = df.drop(['year'], axis=1)
# now convert into the list of dictionaries format as you did before
dicts = df.to_dict(orient='records')
此数据将替换您编写的 df 词典,因此我们将继续这样做:
document_store.write_documents(dicts)
document_store.update_embeddings(retriever=retriever)
现在您可以使用过滤器进行查询,例如要搜索发布年份为 1999 的文档,我们使用条件 "$eq"
(等于):
docs = retriever.retrieve(
"some query here",
top_k=25,
filters={
{"year": {"$eq": 1999}}
}
)
对于1980年之前发表的我们可以使用"$lt"
(小于):
docs = retriever.retrieve(
"some query here",
top_k=25,
filters={
{"year": {"$lt": 1980}}
}
)
我正在尝试使用 Sentence Transformers 和 Haystack 进行文档检索,重点是在文档文本之外的其他元数据上搜索文档。
我正在使用学术出版物标题的数据集,并且附加了一个虚假的出版年份(我想将其用作搜索词)。通过四处阅读,我合并了各列,并在标题和出版年份之间添加了一个分隔符,并包含了列标题,因为我认为这可能会增加上下文。输入示例如下:
title Sparsity-certifying Graph Decompositions [SEP] published year 1980
我这里有一个文档存储和检索方法,基于this:
document_store_faiss = FAISSDocumentStore(faiss_index_factory_str="Flat",
return_embedding=True,
similarity='cosine')
retriever_faiss = EmbeddingRetriever(document_store_faiss,
embedding_model='all-mpnet-base-v2',
model_format='sentence_transformers')
document_store_faiss.write_documents(df.rename(columns={'combined':'content'}).to_dict(orient='records'))
document_store_faiss.update_embeddings(retriever=retriever_faiss)
def get_results(query, retriever, n_docs = 25):
return [(item.content) for item in retriever.retrieve(q, top_k = n_docs)]
q = 'published year 1999'
print('Results: ')
res = get_results(q, retriever_faiss)
for r in res:
print(r)
我检查是否有任何输入实际上具有与搜索词匹配的出版年份,但是当我查看我的搜索结果时,我得到的条目似乎是随机出版年份。我希望至少所有的结果都是相同的出版年份,因为我希望做更复杂的查询,比如 "published year before 1980".
如果有人能告诉我我做错了什么,或者我是否误解了这个过程/预期结果,我们将不胜感激。
听起来您需要元数据过滤而不是将年份放在查询本身中。 FaissDocumentStore
不支持过滤,我建议切换到几天前 Haystack 在 v1.3 版本中引入的 PineconeDocumentStore
。支持当前文档存储集中最强的过滤功能
您需要确保安装了最新版本的 Haystack,它还需要一个额外的 pinecone-client
库:
pip install -U farm-haystack pinecone-client
有一个 guide here 可能会有帮助,它会是这样的:
document_store = PineconeDocumentStore(
api_key="<API_KEY>", # from https://app.pinecone.io
environment="us-west1-gcp"
)
retriever = EmbeddingRetriever(
document_store,
embedding_model='all-mpnet-base-v2',
model_format='sentence_transformers'
)
在编写文档之前,您需要转换数据以在 content
中包含您的文本(正如您在上面所做的那样,但不需要 pre-append 年份),然后包含年份作为 meta
字典中的一个字段。因此,您将创建一个字典列表,如下所示:
dicts = [
{'content': 'your text here', 'meta': {'year': 1999}},
{'content': 'another record text', 'meta': {'year': 1971}},
...
]
我不知道你的 df
的确切格式,但假设它是这样的:
text | year |
---|---|
"your text here" | 1999 |
"another record here" | 1971 |
我们可以编写以下代码来重新格式化它:
df = df.rename(columns={'text': 'content'}) # you did this already
# create a new 'meta' column that contains {'year': <year>} data
df['meta'] = df['year'].apply(lambda x: {'year': x})
# we don't need the year column anymore so we drop it
df = df.drop(['year'], axis=1)
# now convert into the list of dictionaries format as you did before
dicts = df.to_dict(orient='records')
此数据将替换您编写的 df 词典,因此我们将继续这样做:
document_store.write_documents(dicts)
document_store.update_embeddings(retriever=retriever)
现在您可以使用过滤器进行查询,例如要搜索发布年份为 1999 的文档,我们使用条件 "$eq"
(等于):
docs = retriever.retrieve(
"some query here",
top_k=25,
filters={
{"year": {"$eq": 1999}}
}
)
对于1980年之前发表的我们可以使用"$lt"
(小于):
docs = retriever.retrieve(
"some query here",
top_k=25,
filters={
{"year": {"$lt": 1980}}
}
)