初始化 Weaviate 数据库中的 Document 和 Chunk 类

初始化 Weaviate 数据库中的 Document 和 Chunk 类。
它首先获取 Weaviate 客户端实例,然后定义 Chunk 和 Document 的模式。
如果 Document 类已存在,会询问用户是否重写。最后创建或更新模式,并在使用嵌入式数据库时停止它。

def init_schema(model: str = "gpt-3.5-turbo-16k"):
    msg.divider("Creating Document and Chunk class")

    client = setup_client()

    chunk_schema = {
        "classes": [
            {
                "class": "Chunk",
                "description": "Chunks of Documentations",
                "vectorizer": "text2vec-openai",
                "moduleConfig": {
                    "generative-openai": {"model": model}
                },  # gpt-4 / gpt-3.5-turbo
                "properties": [
                    {
                        "name": "text",
                        "dataType": ["text"],
                        "description": "Content of the document",
                    },
                    {
                        "name": "doc_name",
                        "dataType": ["text"],
                        "description": "Document name",
                    },
                    {
                        "name": "doc_type",
                        "dataType": ["text"],
                        "description": "Document type",
                    },
                    {
                        "name": "doc_uuid",
                        "dataType": ["text"],
                        "description": "Document UUID",
                        "moduleConfig": {
                            "text2vec-openai": {
                                "skip": True,  # skip:True排除非语义字段的向量化
                                "vectorizePropertyName": False,  # 不参与向量化
                            }
                        },
                    },
                    {
                        "name": "chunk_id",
                        "dataType": ["number"],
                        "description": "Document chunk from the whole document",
                        "moduleConfig": {
                            "text2vec-openai": {
                                "skip": True,
                                "vectorizePropertyName": False, # 不参与向量化
                            }
                        },
                    },
                ],
            }
        ]
    }

    document_schema = {
        "classes": [
            {
                "class": "Document",
                "description": "Documentation",
                "properties": [
                    {
                        "name": "text",
                        "dataType": ["text"],
                        "description": "Content of the document",
                    },
                    {
                        "name": "doc_name",
                        "dataType": ["text"],
                        "description": "Document name",
                    },
                    {
                        "name": "doc_type",
                        "dataType": ["text"],
                        "description": "Document type",
                    },
                    {
                        "name": "doc_link",
                        "dataType": ["text"],
                        "description": "Link to document",
                    },
                ],
            }
        ]
    }

    if client.schema.exists("Document"):
        user_input = input(
            "此文档已经存在,你想重写吗? (y/n): "
        )
        if user_input.strip().lower() == "y":
            client.schema.delete_class("Document")
            client.schema.delete_class("Chunk")
            client.schema.create(document_schema)
            client.schema.create(chunk_schema)
            msg.good("'Document' and 'Chunk' schemas created")
        else:
            msg.warn("Skipped deleting Document and Chunk schema, nothing changed")
    else:
        client.schema.create(document_schema)
        client.schema.create(chunk_schema)
        msg.good("'Document' and 'Chunk' schemas created")

    if client._connection.embedded_db:
        msg.info("Stopping Weaviate Embedded")
        client._connection.embedded_db.stop()
    msg.info("Done")

在向量数据库中,ChunkDocument 的设计体现了 分块存储元数据管理 的核心思想,以下是它们的关联关系和底层原理:


一、关系:父子层级结构

  • Document(文档):
    表示完整的文档实体,存储 全局元数据(如文档名称、类型、链接等),是逻辑上的完整单位。

  • Chunk(分块):
    表示文档的片段,存储 实际内容分块(如段落或句子)及其向量化结果,是物理上的检索单位。

关联方式
通过 doc_uuid(文档唯一标识符)建立 一对多关系

  • 1 个 Document ➔ 对应 N 个 Chunk
  • 每个 Chunk 通过 doc_uuid 指向其所属的 Document

二、原理:分块存储与检索优化

1. 分块存储的动机
  • 语义粒度控制:
    长文档直接向量化会丢失细节(如 OpenAI 模型有 token 长度限制)。分块后,每个 Chunk 可独立向量化,保留局部语义。
  • 检索效率:
    直接检索文档级向量可能返回不相关内容(如匹配到文档开头但实际答案在结尾)。分块后,检索更精准。
  • 资源优化:
    更新部分内容时,只需重新处理相关 Chunk,无需重构整个文档的向量。
2. 元数据与内容分离
  • Document 的职责:
    • 存储文档的 业务属性(如 doc_link 用于溯源)
    • 提供全局视角(如统计某类文档的分块数量)
  • Chunk 的职责:
    • 存储 可检索的内容text 属性被向量化)
    • 附加分块级元数据(如 chunk_id 记录片段顺序)
3. 向量化与检索流程
# 伪代码示例
document = Document(doc_name="用户手册", doc_type="PDF", doc_link="https://example.com/manual")
chunks = [
    Chunk(text="第一章:安装指南...", doc_uuid=document.uuid, chunk_id=1),
    Chunk(text="第二章:配置参数...", doc_uuid=document.uuid, chunk_id=2)
]

# 向量化时:
for chunk in chunks:
    chunk.vector = openai_embedding(chunk.text)  # 使用 text2vec-openai 生成向量

# 检索时:
query = "如何安装软件?"
query_vector = openai_embedding(query)
results = weaviate.search_chunks(query_vector)  # 返回最匹配的 Chunk
related_document = get_document_by_uuid(results[0].doc_uuid)  # 通过 Chunk 找到原文档

三、设计影响与典型场景

1. 优势
  • 精准检索:
    直接命中相关内容片段(如用户提问“配置参数”时,仅返回第二章的 Chunk)。
  • 灵活更新:
    新增文档时,只需插入新 Chunk 并关联到现有 Document
  • 混合搜索:
    结合向量搜索(语义匹配)和元数据过滤(如 doc_type="PDF")。
2. 典型应用场景
  • 问答系统:
    通过 Chunk 检索答案片段,通过 Document 提供原文链接。
  • 知识库管理:
    统计某类文档(如 doc_type="技术报告")的所有相关 Chunk
  • 增量更新:
    当文档修订时,仅更新变动的 Chunk,无需全量重新向量化。

四、技术细节补充

  1. 向量化跳过非必要字段
    Chunk 中的 doc_uuidchunk_id 设置为 skip: True,避免无意义的文本(如 UUID)污染向量表示。

  2. 生成式扩展
    通过 generative-openai 模块,可直接基于 Chunk 内容生成答案(如 GPT-3.5 补全技术)。

  3. 数据一致性
    删除 Document 时需级联删除其关联的 Chunk(需业务层实现,Weaviate 不自动处理外键)。


总结

Chunk 是向量数据库的 检索主力,负责承载可搜索的语义片段;Document业务逻辑单元,提供上下文管理和溯源能力。两者通过唯一标识符松耦合,兼顾检索效率与元数据管理,是处理长文本、构建语义搜索系统的标准模式。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐