TypeError: unhashable type: ‘list’

用户在 LangChain 框架中使用 MultiQueryRetriever 时,当 Document 的 metadata 字段包含 list(如 {"tags": ["python", "programming"]} )或 dict(如 {"source": {"type": "api"}}

TypeError: unhashable type: 'list'

TypeError: unhashable type: ‘list’

快速结论:该报错发生在 LangChain 的 MultiQueryRetriever.unique_union() 方法中,当 Document 对象的 metadata 字段包含 list 或 dict 类型的值时触发。优先排查 metadata 中是否有列表或字典值,并升级到 LangChain 最新版本。

问题场景

用户在 LangChain 框架中使用 MultiQueryRetriever 时,当 Document 的 metadata 字段包含 list(如 {"tags": ["python", "programming"]})或 dict(如 {"source": {"type": "api"}})类型的值时,调用 unique_union() 方法会抛出 TypeError: unhashable type: 'list' 错误。

报错原文

Traceback (most recent call last):
  File "repro.py", line 10, in <module>
    unique_documents_dict = {
  File "repro.py", line 10, in <dictcomp>
TypeError: unhashable type: 'list'

原因分析

MultiQueryRetriever.unique_union() 方法在去重时,使用以下代码将 metadata 转换为 tuple 作为字典的 key:

unique_documents_dict = {
    (doc.page_content, tuple(sorted(doc.metadata.items()))): doc
    for doc in documents
}

当 metadata 的 value 是 list 或 dict 类型时,sorted(doc.metadata.items()) 会尝试对 list 或 dict 进行排序,但 list 和 dict 是 unhashable 类型,无法作为字典的 key 或参与排序,因此抛出 TypeError

可能原因:元数据设计不当,包含了非标量类型(list/dict)的值。

环境排查

  • Python 版本:3.11.9(用户环境)
  • langchain_core 版本:0.3.86(用户环境)
  • 确认使用的 LangChain 版本是否为最新稳定版
  • 检查 Document 的 metadata 字段是否包含 list 或 dict 类型的值

解决步骤

  1. 升级 LangChain 至最新版本:官方在 main 分支已修复此问题,_unique_documents() 改用基于相等性比较(doc not in documents[:i])的去重方式,不再使用 hash-based dict 方法,因此不会因 metadata 包含 list/dict 而崩溃。
  2. 兼容做法(无需升级版本时):在创建 Document 时,将 metadata 中的 list 或 dict 值转换为可 hash 的类型。例如:
    • 将 list 转换为 tuple:{"tags": tuple(["python", "programming"])}
    • 将 dict 转换为 JSON 字符串或 frozenset:{"source": json.dumps({"type": "api"})}
  3. 检查 custom retriever:如果使用了自定义的 retriever 继承 MultiQueryRetriever,请检查是否重写了 unique_union()_unique_documents() 方法,确保使用安全的去重逻辑。

验证方法

在升级 LangChain 或修改 metadata 后,使用以下代码验证问题是否已解决:

from langchain_core.documents import Document

docs = [
    Document(page_content="hello", metadata={"tags": ["python", "ai"], "source": "web"}),
    Document(page_content="world", metadata={"tags": ["data"], "source": "db"}),
]

# 模拟 unique_union:
unique = {
    (doc.page_content, tuple(sorted(doc.metadata.items()))): doc
    for doc in docs
}
# 如果不再抛出 TypeError,则问题已解决

参考来源

langchain-ai/langchain #38629

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 11168

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注