【Bug已解决】Bug: MultiQueryRetriever.unique_union() crashes on documents with list/dict metadata
【Bug已解决】Bug MultiQueryRetriever.unique_union() crashes on documents with listdict metadata一、现象长什么样这一篇聚焦MultiQueryRetriever.unique_union()在具体文档带 list/dict metadata 时的崩溃和通用 metadata 合并角度不同这里强调文档层面——每个Document对象自带嵌套 metadata当多个变体 query 召回同一篇文档、且该文档 metadata 含list如多标签或dict如来源对象时unique_union在把多条去重成一条时会崩溃。报错通常是TypeError: unhashable type: list或构建集合去重 metadata 键时TypeError: argument of type dict is not iterable更隐蔽的一种它不崩但把 list 直接当标量update覆盖导致被哪些 query 命中的标签信息只剩下最后一个 query 的丢失了多 query 召回的语义价值。二、背景MultiQuery 的典型用法一个问题 → LLM 生成 N 个改写 query → 每个 query 各自retriever.get_relevant_documents→ 把 N 批结果unique_union合并。合并时按page_content去重把同一文档的多条记录合成一条并试图合并 metadata以记录它来自哪些 query。但真实文档的 metadata 往往不是扁平标量tags是 listsource_info是 dictchunk_path可能是 list of str。当unique_union对这些值做集合去重或update 覆盖时就触发上述崩溃或静默丢失。本篇与 845 的区别845 站在metadata 合并函数视角讲类型分支本篇站在Document 对象去重视角强调多 query 召回同一文档时的 list/dict 处理并给出面向Document的修复。三、根因根因在unique_union的 Document 级去重对 Document.metadata 做set()去重想把多条记录的 metadata 键合并唯一但值里有 list/dict构造集合时因不可哈希崩溃。metadata.update(other.metadata)覆盖把后一条的 metadata 整块盖到前一条list 值被整体替换丢失多 query 命中的累积信息比如queries_hit: [q1,q2]变成只有[q2]。未区分文档自带的嵌套 metadata与union 过程产生的聚合字段把两者混在一起处理越搞越乱。本质去重逻辑把 Document 的 metadata 当成可自由集合化的扁平字典忽略了真实文档 metadata 的嵌套性与聚合字段应累积的语义。四、最小可运行复现下面缩略逻辑复现文档级崩溃def bad_unique_union_docs(docs): by_content {} for d in docs: c d.page_content if c not in by_content: by_content[c] d else: # 想合并 metadata 的键集合 keys set(by_content[c].metadata) | set(d.metadata) # 若值是 list/dict 这里不直接崩 merged {} for k in keys: a by_content[c].metadata.get(k) b d.metadata.get(k) # 对 list 值做 set 去重 - 崩溃 merged[k] list(set(a) | set(b)) by_content[c] type(d)(page_contentc, metadatamerged) return list(by_content.values()) docs [ type(D, (), {page_content: X, metadata: {tags: [a]}})(), type(D, (), {page_content: X, metadata: {tags: [b]}})(), ] bad_unique_union_docs(docs) # TypeError: unhashable type: list五、解决方案第一层最小直接修复最小修法写一个 Document 感知的合并对 list 值拼接去重、dict 值深合并、标量覆盖且为 union 过程产生的聚合字段如命中的 query 列表做累积。def merge_doc_meta(a: dict, b: dict) - dict: out dict(a) for k, v in b.items(): if k not in out: out[k] v elif isinstance(out[k], list) and isinstance(v, list): out[k] out[k] [x for x in v if x not in out[k]] elif isinstance(out[k], dict) and isinstance(v, dict): out[k] {**out[k], **v} else: out[k] v return out def safe_unique_union_docs(docs): by_content {} for d in docs: c d.page_content if c not in by_content: by_content[c] d else: merged merge_doc_meta(by_content[c].metadata, d.metadata) by_content[c] type(d)(page_contentc, metadatamerged) return list(by_content.values())这一层让带嵌套 metadata 的文档去重不再崩溃且 list 标签被累积。六、解决方案第二层结构化改进把Document 级 metadata 合并固化成策略对象作为单一事实来源并显式区分文档自带字段与聚合字段。from dataclasses import dataclass, field from typing import Any, Dict, List dataclass(frozenTrue) class LangChainMultiQueryMetaCrashPolicy: MultiQuery Document 去重合并策略的单一事实来源。 list_merge: str concat_dedup dict_merge: str deep aggregate_keys: List[str] field(default_factorylambda: [queries_hit]) aggregate_mode: str accumulate # accumulate | overwrite def merge_value(self, a: Any, b: Any) - Any: if isinstance(a, list) and isinstance(b, list): return a [x for x in b if x not in a] if self.list_merge concat_dedup else b if isinstance(a, dict) and isinstance(b, dict): return {**a, **b} if self.dict_merge deep else b return b def merge(self, a: Dict, b: Dict) - Dict: out dict(a) for k, v in b.items(): if k in self.aggregate_keys and self.aggregate_mode accumulate: out[k] (out.get(k, []) [v]) if not isinstance(out.get(k), list) \ else out[k] [x for x in (v if isinstance(v, list) else [v]) if x not in out[k]] elif k in out: out[k] self.merge_value(out[k], v) else: out[k] v return out def validate(self) - None: if self.aggregate_mode not in (accumulate, overwrite): raise AssertionError(bad aggregate_mode)这样unique_union对每个 Document 调用policy.merge嵌套结构与聚合字段都有确定语义。七、解决方案第三层断言 / CI 守护用 pytest 锁死 Document 级合并import pytest from policy import LangChainMultiQueryMetaCrashPolicy as P class Doc: def __init__(self, page_content, metadata): self.page_content page_content self.metadata metadata def test_nested_no_crash(): p P() docs [ Doc(X, {tags: [a], src: {f: 1}}), Doc(X, {tags: [b], src: {g: 2}}), ] by {} for d in docs: by[d.page_content] d if d.page_content not in by \ else Doc(d.page_content, p.merge(by[d.page_content].metadata, d.metadata)) m by[X].metadata assert m[tags] [a, b] assert m[src] {f: 1, g: 2} def test_aggregate_queries_hit(): p P() a {queries_hit: [q1]} b p.merge(a, {queries_hit: [q2]}) assert b[queries_hit] [q1, q2] def test_policy_valid(): P().validate()CI 加一条MultiQueryRetriever单测必须构造带 list/dict metadata 的真实 Document走unique_union断言不抛TypeError。八、排查清单unique_union在真实文档上崩unhashable type→ metadata 值被set()需类型分支。多 query 命中信息只剩最后一个→ list 值被update覆盖应累积。是否区分文档自带 metadata与聚合字段→ 聚合字段如 queries_hit应 accumulate。dict metadata 合并是否符合预期→ 深合并而非覆盖。是否只对 metadata 键做集合→ 值也可能嵌套不能假设扁平。与 845 的关系→ 本文档级视角845 是函数级视角可共用同一策略类。九、小结MultiQueryRetriever.unique_union()在处理带 list/dict metadata 的真实 Document时因对 metadata 值做集合去重或整块覆盖而崩溃/静默丢失。与 845 的合并函数类型分支互补本篇从 Document 去重视角给出修复对 list 拼接去重、dict 深合并并为多 query 命中这类聚合字段做累积。策略固化于LangChainMultiQueryMetaCrashPolicy并用 pytest CI 守护。多 query 召回合并的通用原则同一文档被多个 query 命中时metadata 应当累积而非覆盖且嵌套结构必须类型感知。

相关新闻

APK安装器避坑指南:不用模拟器,4步让Windows直装安卓应用

APK安装器避坑指南:不用模拟器,4步让Windows直装安卓应用

APK安装器避坑指南:不用模拟器,4步让Windows直装安卓应用 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 周末想在大屏上玩《我的世界》手机版&…

2026/8/20 7:58:21 阅读更多 →
【Bug已解决】Bug: EnsembleRetriever silently overwrites metadata when documents share page_content

【Bug已解决】Bug: EnsembleRetriever silently overwrites metadata when documents share page_content

【Bug已解决】Bug: EnsembleRetriever silently overwrites metadata when documents share page_content 一、现象长什么样 EnsembleRetriever 把多个底层 retriever(比如 BM25 向量检索)的结果按权重融合,产出一份 Document 列…

2026/8/23 23:53:31 阅读更多 →
10万元级豪华平替车深度评测:北汽绅宝智道能否对标奔驰C级?

10万元级豪华平替车深度评测:北汽绅宝智道能否对标奔驰C级?

1. 一次关于“价值平替”的深度试驾体验 最近在后台和评论区,经常看到有朋友在问一个很有意思的问题:预算有限,但又想体验豪华品牌中型车的质感,有没有什么靠谱的选择?这个话题其实挺现实的,毕竟不是每个人…

2026/8/17 18:21:30 阅读更多 →

最新新闻

怎么建立一个能够发现“未知互联网资产”的暴露面监控体系

怎么建立一个能够发现“未知互联网资产”的暴露面监控体系

1. 网络空间测绘平台 这个是最直接的方式。即使 IP 不在你的扫描范围,Shodan、FOFA、ZoomEye、Quake、Hunter 等平台也可能已经扫过它。 关键不是扫 IP,而是用“厂商特征”去搜: 证书组织名域名备案信息favicon hashJS 文件 hash页面 titleHT…

2026/8/26 20:01:44 阅读更多 →
Repo Chat快速上手教程:10分钟从零搭建你的GitHub仓库AI代码问答系统

Repo Chat快速上手教程:10分钟从零搭建你的GitHub仓库AI代码问答系统

Repo Chat快速上手教程:10分钟从零搭建你的GitHub仓库AI代码问答系统 【免费下载链接】repo-chat Use AI to ask questions about any GitHub repo. 项目地址: https://gitcode.com/gh_mirrors/re/repo-chat Repo Chat 是一个开源的 GitHub 仓库 AI 代码问答…

2026/8/26 20:01:44 阅读更多 →
currency Formatter教程:多语言货币格式化与解析的10个实用技巧

currency Formatter教程:多语言货币格式化与解析的10个实用技巧

currency Formatter教程:多语言货币格式化与解析的10个实用技巧 【免费下载链接】currency Currency handling for Go. 项目地址: https://gitcode.com/gh_mirrors/cu/currency currency 是一个为 Go 语言打造的货币处理库,基于 CLDR v48 数据&am…

2026/8/26 20:01:44 阅读更多 →
volrend 体渲染器双后端揭秘:CUDA 与片元着色器后端的性能差异与取舍指南

volrend 体渲染器双后端揭秘:CUDA 与片元着色器后端的性能差异与取舍指南

volrend 体渲染器双后端揭秘:CUDA 与片元着色器后端的性能差异与取舍指南 【免费下载链接】volrend PlenOctree Volume Rendering (supports CUDA & fragment shader backends) 项目地址: https://gitcode.com/gh_mirrors/vo/volrend volrend 是一个用 C…

2026/8/26 20:01:44 阅读更多 →
CipherChat的System Prompt工程深剖:为什么few-shot演示能让GPT-4乖乖破解密码

CipherChat的System Prompt工程深剖:为什么few-shot演示能让GPT-4乖乖破解密码

CipherChat的System Prompt工程深剖:为什么few-shot演示能让GPT-4乖乖破解密码 【免费下载链接】CipherChat A framework to evaluate the generalization capability of safety alignment for LLMs 项目地址: https://gitcode.com/gh_mirrors/ci/CipherChat …

2026/8/26 20:01:44 阅读更多 →
Ornith-1.5 自我改进范式深度剖析:任务生成、脚手架与 Rollout 联合强化学习如何炼出 397B 旗舰

Ornith-1.5 自我改进范式深度剖析:任务生成、脚手架与 Rollout 联合强化学习如何炼出 397B 旗舰

Ornith-1.5 自我改进范式深度剖析:任务生成、脚手架与 Rollout 联合强化学习如何炼出 397B 旗舰 【免费下载链接】Ornith-1.5-397B 项目地址: https://ai.gitcode.com/hf_mirrors/ornith-ai/Ornith-1.5-397B Ornith-1.5-397B 是 ornith-ai 团队推出的自我改…

2026/8/26 20:00:44 阅读更多 →

日新闻

Python random 模块常用函数详解:从入门到实战

Python random 模块常用函数详解:从入门到实战

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要: 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数(random()、unifor…

2026/8/26 0:00:40 阅读更多 →
《Microsoft Sql server 2008 Internals》读书笔记--第三章Databases and Database Files(2)

《Microsoft Sql server 2008 Internals》读书笔记--第三章Databases and Database Files(2)

《Microsoft Sql server 2008 Internals》索引目录: 《Microsoft Sql server 2008 Internals》读书笔记--目录索引 在上篇文章中,主要介绍了创建数据库的基本语法和FileGroup的初步知识。需要注意的是: 关于FileGroup 如果你的系统是用Raid设备直接存…

2026/8/26 1:18:18 阅读更多 →
政务AI智能体怎么建?三种模式、三步路径与四个误区

政务AI智能体怎么建?三种模式、三步路径与四个误区

政务AI智能体已经从概念试点阶段,转入了政务服务的常态化落地应用;在实际使用过程中,它能自主理解办事需求、辅助完成填报申报、开展材料预审,并联动多个系统协同作业,真正嵌入到政务办理的全流程当中。但在落地推进过…

2026/8/26 1:18:18 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/26 14:45:33 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/26 17:46:43 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/26 14:46:37 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/26 3:50:20 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/26 17:46:39 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/26 1:24:05 阅读更多 →