文档已经是字典,为什么还要写row = dict(doc)?
dict(doc)创建新的外层字典,避免附加向量时直接修改DOCS中的原始文档。
DETAILED ANSWER
直接结论
doc确实已经是字典,但dict(doc)的目的不是把它“转换成字典”,而是创建一个新的外层字典。这样给row增加title_vector和content_vector时,不会直接修改DOCS里的原始文档。
不复制会发生什么
如果写成:
row = doc
row["title_vector"] = title_vector
row和doc只是同一个字典对象的两个名字:
row ──┐
├──> 同一个字典
doc ──┘
修改row就等于修改doc,而doc又来自DOCS,所以原始数据也会被加入向量字段。
dict(doc)做了什么
row = dict(doc)
执行后,外层字典变成两个不同对象:
doc ──> 原始字典
row ──> 新的外层字典
它们一开始拥有相同的键和值,但增加或删除row最外层的键,不会影响doc:
row["title_vector"] = title_vector
row["content_vector"] = content_vector
因此代码完成的是:
保留原始文档字段
+ 附加标题向量
+ 附加正文向量
→ 形成准备写入向量数据库的新记录
为什么叫浅拷贝
dict(doc)只复制最外层字典,里面已有的可变对象仍可能被共享。
doc = {
"title": "示例",
"tags": ["Python", "RAG"],
}
row = dict(doc)
此时:
row["title"] = "新标题"
不会改变doc["title"],因为是在替换row最外层的值;但是:
row["tags"].append("向量数据库")
会同时影响doc["tags"],因为两个字典仍引用同一个列表。
如果需要连嵌套列表和嵌套字典也完全独立,才考虑copy.deepcopy(doc)。
放回原代码理解
rows = []
for doc, title_vector, content_vector in zip(
DOCS,
title_vectors,
content_vectors,
):
row = dict(doc)
row["title_vector"] = title_vector
row["content_vector"] = content_vector
rows.append(row)
每轮都从原始文档复制出一条新记录,再附加与该文档同位置的两个向量,最后放入rows。原始DOCS仍保持只有pk、title、content和category等字段。
