llama_index [Bug]: 当元数据包含在Weaviate向量存储中时,文档插入失败,

irlmq6kh  于 2个月前  发布在  其他
关注(0)|答案(4)|浏览(32)

Bug描述

你好,
当我尝试使用Weaviate向量存储时,我发现当我尝试向其中插入一个带有元数据的文档时,它实际上并没有插入到向量存储中。请注意,没有引发异常或警告。只有在尝试打印向量存储的内容或使用检索器时,才能检测到失败。
如果文档不包含元数据,则插入已完成,检索器可以在文档的块上进行搜索。我们在Discord上与@logan-markewich进行了交谈,这个问题可能与Weaviate issue #5202有关。

版本

0.10.51 (llama-index)
1.0.0 (llama-index-vector-stores-weaviate)
4.6.5 (weaviate-client)

重现步骤

创建一个Weaviate向量存储索引,然后尝试插入一个带有元数据的文档和一个不带元数据的文档。然后使用检索器检索节点或使用Weaviate method for listing查看集合的内容,并检查带有元数据的文档中的节点是否包含在结果中。以下是从Jupyter Notebook中提取的Python代码,以展示重现步骤。

iq0todco

iq0todco1#

你在使用元数据插入Weaviate矢量存储时遇到的问题可能源于插入过程中如何处理元数据。以下是一些步骤和建议,可以帮助调试并解决这个问题:

  1. 检查元数据转换:
    确保在插入之前正确地转换和结构化元数据。node_to_metadata_dict 函数负责这个转换。如果元数据结构无效,可能会导致插入默默失败。
def node_to_metadata_dict(
    node: BaseNode,
    remove_text: bool = False,
    text_field: str = DEFAULT_TEXT_KEY,
    flat_metadata: bool = False,
) -> Dict[str, Any]:
    """Common logic for saving Node data into metadata dict."""
    node_dict = node.dict()
    metadata: Dict[str, Any] = node_dict.get("metadata", {})

    if flat_metadata:
        _validate_is_flat_dict(metadata)

    # store entire node as json string - some minor text duplication
    if remove_text:
        node_dict[text_field] = ""

    # remove embedding from node_dict
    node_dict["embedding"] = None

    # dump remainder of node_dict to json string
    metadata["_node_content"] = json.dumps(node_dict)
    metadata["_node_type"] = node.class_name()

    # store ref doc id at top level to allow metadata filtering
    metadata["document_id"] = node.ref_doc_id or "None"  # for Chroma
    metadata["doc_id"] = node.ref_doc_id or "None"  # for Pinecone, Qdrant, Redis
    metadata["ref_doc_id"] = node.ref_doc_id or "None"  # for Weaviate

    return metadata
  1. 添加日志进行调试:
    在插入之前添加日志以检查元数据的内容。这将有助于识别可能导致静默失败的元数据中的任何问题。
import logging

def add_node(
    client: "WeaviateClient",
    node: BaseNode,
    class_name: str,
    batch: Optional[Any] = None,
    text_key: str = DEFAULT_TEXT_KEY,
) -> None:
    """Add node."""
    metadata = {}
    metadata[text_key] = node.get_content(metadata_mode=MetadataMode.NONE) or ""

    additional_metadata = node_to_metadata_dict(
        node, remove_text=True, flat_metadata=False
    )
    metadata.update(additional_metadata)

    vector = node.get_embedding()
    id = node.node_id

    # Log metadata for debugging
    logging.debug(f"Inserting node with metadata: {metadata}")

    # if batch object is provided (via a context manager), use that instead
    if batch is not None:
        batch.add_object(
            properties=metadata, collection=class_name, uuid=id, vector=vector
        )
    else:
        client.collections.get(class_name).data.insert(
            properties=metadata, uuid=id, vector=vector
        )
  1. 确保元数据符合Weaviate的要求:
    元数据字典必须是扁平的,键为字符串,值为一种类型:字符串、整数、浮点数或None。确保你的元数据符合这些要求。
def class_schema_exists(client: Any, class_name: str) -> bool:
    """Check if class schema exists."""
    validate_client(client)
    return client.collections.exists(class_name)

def create_default_schema(client: Any, class_name: str) -> None:
    """Create default schema."""
    validate_client(client)
    class_schema = {
        "class": class_name,
        "description": f"Class for {class_name}",
        "properties": NODE_SCHEMA,
    }
    client.collections.create_from_dict(class_schema)
  1. 检查模式是否存在:
    在插入文档之前,确保类的模式存在。如果模式不存在,需要创建它。
    x1a3b1x

通过遵循这些步骤,你应该能够识别并解决将带有元数据的文档插入Weaviate矢量存储的问题。如果问题仍然存在,可能需要进一步调查特定的元数据结构和Weaviate对元数据的处理方式。要继续与 Dosu 对话,请提及 @dosu。

b1zrtrql

b1zrtrql2#

这里的问题是属性名的空间。
"title of parental document"
这段代码可以正常工作:

llama_index_doc = Document(doc_id='12345',
                           text=text,
                           metadata={
                               "title_of_parental_document": "Regression analysis",
                               "source": "https://en.wikipedia.org/wiki/Regression_analysis"
                           })

但这段代码的问题在于元数据的名称不符合Weaviate所期望的规范:
https://weaviate.io/developers/weaviate/config-refs/schema#properties
例如:
/[_A-Za-z][_0-9A-Za-z]*/
我认为我们可以在这里添加一些内容,将属性名规范化为符合Weaviate支持的格式。

nkoocmlb

nkoocmlb3#

非常感谢@dudanogueira!
现在它完美地工作了!
我最初的想法是在名称不符合Weaviate规则的情况下引发异常,例如检查集合名称的实现(我指的是这段代码)。我认为这已经足够了,因为这样用户就会清楚地知道名称必须是什么。但当然,你也知道这里更好的方法。

7vhp5slm

7vhp5slm4#

我同意,抛出错误比更改元数据名称更好,因为这可能导致意外的结果。

相关问题