杠精派
派聪明
0/512

热门评论

未来可期 2026年03月12日 22:53
引用原文:关键词检索部分用的是 BM25
@派聪明,向量检索和关键词检索是同时进行的吗?topK是什么时候用到的
点赞
回复5 取消回复
派聪明 2026年03月12日 22:55
向量检索和关键词检索不是同时进行的,而是采用"混合检索"的两阶段策略: 1. **第一阶段(召回)**:先使用向量检索(如KNN)从知识库中召回一个较大的候选集,通常是topK的30倍左右。这一阶段主要看语义相似度,确保不漏掉任何可能相关的文档。 2. **第二阶段(重排)**:对召回的候选集使用BM25进行关键词匹配和重排序。这一阶段确保结果既语义相关又包含用户查询的关键词。 **topK参数的使用时机**: - 在第一阶段,系统会召回比最终topK多得多的候选结果(如topK的30倍) - 在第二阶段,系统会对这些候选结果进行BM25重排序 - 最终,根据向量得分和BM25得分的加权综合得分,选出前topK条结果返回给用户 这种"先召回后重排"的方式结合了向量检索的广度(能找到语义相关但关键词不完全匹配的文档)和关键词检索的精度(确保结果包含用户查询的关键词),提高了检索的准确性和全面性。
点赞
回复 取消回复
展开剩余 4 条回复

85 条评论

李辰龙 2026年05月06日 16:10
引用原文:zhongchu
@杠精派 为什么不用汉字
点赞
回复 取消回复
leeko 2026年04月23日 15:38
@派聪明 KNN和MB25最后的得分有没有进行归一化之后再进行权重相加
点赞
回复 取消回复
zhiwenfan 2026年04月20日 12:36
引用原文: rescore
什么东西
点赞
回复 取消回复
🇸 🇺 🇳 2026年04月16日 17:29
引用原文:首先是内存瓶颈,HNSW 图结构需要完全加载到 JVM 堆内存中。随着向量数量和维度的增加,内存消耗会急剧上升,成为单个节点容量的主要限制因素。
@派聪明 说下你们公司项目是使用多大内容存储 ES
点赞
回复 取消回复
Toran 2026年04月08日 22:15
@派聪明 ,使用AOP实现了什么功能?
点赞
回复 取消回复
借我 2026年04月02日 21:52
引用原文:这种场景下,关键词匹配反而比语义更准。所以我们是先用向量去做初筛,再通过 BM25 的 rescore 对初筛结果再排序,这样能把那些“语义匹配 + 关键词命中”的高质量结果排到前面。
在rescore之前不是还有一次BM25检索吗@派聪明
点赞
回复 取消回复
柒眠 2026年03月29日 22:00
引用原文:比如说当一个用户(比如“王二”)发起检索请求时,请求会携带他的身份认证信息(也就是 JWT Token)。后端在收到请求后,会解析这个 Token,拿到用户的 userid,再从 Redis 缓存中取出用户的组织标签等信息。
@派聪明 Redis缓存中有存储用户的组织标签等信息吗
点赞
回复3 取消回复
派聪明 2026年03月29日 22:00
根据参考资料中的描述,**是的,Redis缓存中存储了用户的组织标签等信息**。具体实现流程如下: ### 详细说明: 1. **用户身份认证** 用户(如“王二”)发起检索请求时,请求中会携带JWT Token。后端解析Token获取用户的`userid`。 2. **从Redis缓存读取权限信息** 后端使用`userid`作为键,从**Redis缓存**中查询该用户的权限相关信息,包括: - **组织标签(`orgTag`)**:用户所属的组织/部门标签列表。 - 其他可能权限相关的元数据(如角色、权限范围等)。 3. **权限过滤逻辑** 后端将Redis中获取的组织标签等信息,直接嵌入到Elasticsearch的查询条件中,通过`filter`子句实现权限过滤: ```java // 条件3:用户所在组织的文档(从Redis获取的orgTag) permissionBoolQuery.should(s -> s.terms(t -> t .field("orgTag") .terms(loginUser.getOrgTags()) // 直接使用Redis缓存的标签 )); ``` ### 为什么使用Redis缓存? - **性能优化**:避免每次查询都访问数据库,减少权限验证的延迟。 - **高频访问场景**:权限信息在检索过程中需频繁调用,Redis的内存特性可提供毫秒级响应。 - **数据一致性**:通过合理的缓存策略(如TTL失效)确保权限信息的时效性。 ### 总结: Redis在此系统中承担**用户权限信息的缓存层**作用,存储了`userid`对应的组织标签等关键数据,用于在检索时快速实现权限隔离,确保用户只能访问其有权限的文档(公开文档、自身文档或组织内文档)。
点赞
回复 取消回复
展开剩余 2 条回复
心已指南 2026年03月29日 14:38
@派聪明 结合 KNN 向量召回与 BM25 重排序,实现“关键词+语义”双引擎检索。怎么理解这句话
点赞
回复1 取消回复
派聪明 2026年03月29日 14:41
结合KNN向量召回与BM25重排序实现“关键词+语义”双引擎检索,本质是通过**两阶段策略**融合语义理解与关键词匹配,提升检索精准度。以下是分步解析: --- ### **1. 双引擎的核心机制** - **KNN向量召回(语义引擎)** - **作用**:将用户查询转换为高维向量(通过Embedding模型),在向量空间中查找语义最接近的文档(如“如何提升工作效率”匹配“时间管理技巧”)。 - **优势**:突破关键词限制,理解语义关联(同义、上下文等)。 - **实现**:Elasticsearch的`knn`查询,基于余弦相似度计算向量距离。 - **BM25重排序(关键词引擎)** - **作用**:对KNN召回的候选集(如top 30倍结果)进行关键词匹配,优先返回包含专有名词、精确术语的文档(如“Python错误码”匹配含“Python”和“错误码”的文档)。 - **优势**:精准匹配显式关键词,避免语义检索对专有名词的“泛化”偏差。 - **实现**:通过Elasticsearch的`rescore`机制,对候选集重新计算BM25得分(结合词频、文档长度、关键词稀有度)。 --- ### **2. 两阶段协同流程** ```mermaid graph LR A[用户输入] --> B[Embedding转向量] B --> C[KNN召回top 30倍候选集] C --> D[BM25重排序] D --> E[加权合并得分] E --> F[返回topK结果] ``` - **阶段1:语义召回(求全)** KNN检索覆盖所有语义相关文档,避免遗漏“意思相近但关键词不同”的结果(如问“手机”召回“智能手机”)。 - **阶段2:关键词精排(求精)** BM25对候选集重排,将“语义匹配+关键词命中”的高质量结果前置(如同时含“手机”和“苹果”的文档排到最前)。 --- ### **3. 权重设计(关键优化)** - **向量得分权重(0.2)**:保留语义相关性,避免因关键词缺失丢弃优质结果。 - **BM25得分权重(1.0)**:强化关键词精准度,确保专有名词优先级。 ```java .queryWeight(0.2d) // KNN分数占比20% .rescoreQueryWeight(1.0d) // BM25分数占比80% ``` --- ### **4. 双引擎的互补价值** | **检索方式** | **优势** | **局限性** | **双引擎解决方案** | |--------------|----------|------------|-------------------| | **纯KNN(语义)** | 理解同义词、上下文 | 对专有名词不敏感 | BM25补强关键词匹配 | | **纯BM25(关键词)** | 精准匹配术语 | 无法理解语义关联 | KNN扩展召回范围 | > **示例**: > 用户输入:“如何解决电脑蓝屏” > - KNN召回:含“系统崩溃”“死机”的文档(语义相关)。 > - BM25重排:优先含“蓝屏”“错误代码0x000000”的文档(关键词精准)。 --- ### **5. 技术实现要点** - **Elasticsearch配置**: - 向量字段:`dense_vector`(2048维)+ `index: true`(启用HNSW索引)。 - 关键词字段:`text`类型 + 中文分词器(如IK分词)。 - **权限过滤**:在查询阶段通过`filter`子句隔离无权限数据(如`orgTag`、`userId`)。 --- ### **总结** “关键词+语义”双引擎本质是**用KNN解决“能不能找到”**(语义覆盖),**用BM25解决“准不准确”**(关键词精炼),通过两阶段协作实现“无遗漏+高精度”的检索效果。这种设计尤其适用于企业知识库等需兼顾语义理解与术语精确匹配的场景。
点赞
回复 取消回复
鲸落 2026年03月26日 22:19
引用原文:topK 用来控制最后返回给前端的结果数量,默认是 10 条。但真正有意思的是,这个 topK 并不是简单地“查10条就结束”,而是经过了两个阶段的混合排序流程。 第一阶段是向量召回,主要看语义相似度。举个例子,如果用户问的是“如何提升工作效率”,那即便知识库里没有完全一样的问题,但只要有文章讨论的是“时间管理技巧”或“效率工具推荐”,因为它们在语义空间上很接近,也能被召回。这一步我们一般会放宽范围,比如召回 topK 的 30 倍,这样能最大化地覆盖语义相关内容。
这一段代码的具体执行流程是什么,为什么要用lambda表达式?
点赞
回复 取消回复
(·__·) 2026年03月26日 21:04
引用原文:能不能用 filter 替代 query
@派聪明, 为什么这样能提升效率
点赞
回复1 取消回复
派聪明 2026年03月26日 21:06
在Elasticsearch中,使用`filter`替代`query`能显著提升查询效率,核心原因在于两者的**计算逻辑**和**缓存机制**存在本质差异: --- ### **1. 避免相关性计算(Scoring)** - **`query`**: 需对每个匹配文档计算相关性得分(如BM25、向量相似度等),涉及复杂算法(如词频统计、向量距离计算),消耗大量CPU资源。 - **`filter`**: 仅判断文档是否满足条件(如`isPublic: true`),**不计算得分**,直接返回`true/false`,计算开销极小。 > ✅ **效果**:权限过滤、标签匹配等二值逻辑场景下,`filter`比`query`快10倍以上。 --- ### **2. 利用缓存机制** - **`filter`的结果会被缓存**: ES会缓存`filter`的匹配结果(如`userId: "xxx"`或`orgTag: ["A","B"]`),后续相同查询可直接命中缓存,跳过底层扫描。 - **`query`的缓存效率低**: 涉及相关性计算的查询(如关键词匹配、KNN)因参数变化频繁(如不同查询词),缓存命中率极低。 > 📌 **示例**: > 用户权限过滤条件(`userId: "王二"`)在短时间内可能重复出现,ES缓存后后续请求直接返回结果,无需重新扫描索引。 --- ### **3. 查询流程优化** - **`query` + `filter`组合**: ```json { "query": { // 计算相关性得分 "bool": { "must": [ {"knn": {"vector": {"vector": [0.1, 0.2, ...], "k": 10}}}, {"match": {"textContent": "如何提升效率"}} ] } }, "filter": { // 仅做权限过滤,不参与排序 "bool": { "should": [ {"term": {"isPublic": true}}, {"term": {"userId": "王二"}}, {"terms": {"orgTag": ["部门A", "部门B"]}} ] } } } ``` - **`filter`独立于`query`**: 权限过滤在`filter`子句中,不影响相关性得分计算,且优先执行(减少无效计算)。 - **性能对比**: 若权限过滤放在`query`的`must`中,ES需先计算所有文档的相关性得分,再过滤权限,效率骤降。 --- ### **4. 适用场景** - **`filter`的典型场景**: 权限控制(如`userId`、`orgTag`、`isPublic`)、时间范围过滤、状态筛选等**二值逻辑**。 - **`query`的典型场景**: 需要排序的语义搜索(如KNN)、关键词匹配(BM25)等**相关性计算**场景。 --- ### **总结** | **特性** | `query` | `filter` | |----------------|----------------------------------|----------------------------------| | **计算目标** | 相关性得分(Scoring) | 布尔匹配(True/False) | | **资源消耗** | 高(CPU密集) | 低(快速判断) | | **缓存机制** | 缓存命中率低(参数多变) | 缓存命中率高(条件固定) | | **适用场景** | 需排序的语义/关键词搜索 | 权限过滤、标签筛选等二值逻辑 | > 💡 **优化建议**: > 将权限过滤、状态筛选等**非排序条件**全部放入`filter`,可减少70%+的查询延迟(尤其高并发场景)。
点赞
回复 取消回复

目录