RAG-Fusion:多查询融合检索增强生成技术原理与工程实践

news2026/5/4 15:48:39
1. 项目概述当RAG遇上“融合”思维最近在折腾检索增强生成RAG应用的朋友可能都遇到过这样一个痛点用户的一个问题背后可能藏着好几种不同的问法。比如用户问“如何提高Python代码的运行速度”他可能真正关心的是“代码优化技巧”、“算法复杂度降低”或者“并行计算”。传统的RAG流程用一个查询去向量库搜一遍很可能只命中了一部分相关文档导致生成的答案不够全面甚至遗漏关键信息。我最近深度使用并改造了一个名为Raudaschl/rag-fusion的项目它直击的就是这个痛点。这个项目的核心思想不是用单一查询去检索而是先让大语言模型LLM根据原始问题生成多个不同角度、不同表述的相关查询Query Variations然后用这组查询去并行检索最后用一种巧妙的算法对所有检索结果进行去重、重排序和融合最终得到一份更全面、更相关的上下文再喂给LLM生成最终答案。简单来说它把“一问一答”变成了“多问多答择优融合”。这听起来像是简单的查询扩展但rag-fusion在结果融合排序上的算法 Reciprocal Rank Fusion, RRF才是其精髓所在它能有效解决不同查询返回结果的质量和排序差异问题。这个项目非常适合那些已经搭建了基础RAG流水线但感觉检索召回率Recall和答案质量遇到瓶颈的开发者。接下来我将从设计思路、核心实现、实操调优到避坑指南完整拆解这个项目并分享我将其集成到生产级应用中的实战经验。2. 核心架构与设计哲学拆解2.1 从“单一检索”到“多路召回”的范式转变传统RAG的流程可以概括为用户查询 - 向量化 - 向量数据库相似性搜索 - 返回Top-K文档 - 组合成上下文 - LLM生成答案。这个链条的脆弱环节在于第一步的“用户查询”。如果查询表述模糊、不专业或者与文档库中的措辞差异较大检索质量就会急剧下降。rag-fusion引入了一个前置的“查询生成”层。它的设计哲学是承认并利用LLM在理解语义和进行文本改写方面的强大能力。与其依赖用户那一个可能不完美的查询不如让LLM基于这个查询模拟出多个“理想用户”或“领域专家”可能会提出的问题。例如对于“机器学习模型过拟合怎么办”LLM可能会生成“机器学习中过拟合的定义和常见表现有哪些”“预防和减轻模型过拟合的具体技术有哪些”“L1/L2正则化是如何解决过拟合的”“在训练中早停法Early Stopping如何操作”这每一个生成的问题都是一条独立的检索路径。这种“多路召回”的机制极大地提高了命中相关文档的概率相当于用多个渔网在不同位置捕鱼总比一张网捞到的东西多。2.2 融合排序算法RRF的核心价值生成了多个查询并检索后我们会得到多组排序不同的文档列表。如何将这些列表合并成一个最终的最优列表这是融合阶段的核心挑战。简单拼接去重会丢失排序信息按原始分数加权平均又面临不同向量模型分数尺度不一致、不可比的问题。rag-fusion采用了倒数排序融合Reciprocal Rank Fusion, RRF算法。这是一个在信息检索领域被验证有效的、无需分数校准的融合方法。它的计算公式非常巧妙对于一个文档d它在最终列表中的RRF分数计算如下RRFscore(d) Σ (1 / (k rank_i(d)))其中rank_i(d)是文档d在第i个查询返回结果列表中的排名如果未出现则此项不计入。k是一个常数通常设为60这是一个经验值用于平滑那些排名非常靠后的文档的影响。为什么RRF有效它的核心思想是一个文档在多个列表中的排名都很靠前比它在某一个列表中排名第一但在其他列表中不见踪影更能证明其普遍相关性。公式中的倒数1/rank赋予了高排名小数字更大的权重而常数k确保了即使排名靠后比如100名开外其贡献也不会完全为零但会非常小。这种融合方式不依赖于原始的相似度分数只依赖于排名因此完美规避了不同检索系统分数标准化的问题。注意原项目默认k60这是一个在多个信息检索基准测试中表现良好的值。但在实际应用中如果你的查询生成数量少如3-4个或者希望排名的影响更“尖锐”可以适当调小k值如30如果查询生成数量多且希望给尾部文档多一点机会可以调大k值。这是一个需要根据你的数据和效果微调的超参数。2.3 项目组件与工作流全景基于以上思想rag-fusion的工作流可以清晰地划分为四个阶段我将其总结为“生成-检索-融合-生成”闭环查询生成Query Generation使用一个LLM如GPT-3.5/4, Claude, 或本地模型基于原始查询生成N个相关的变体查询。这里的关键是设计好的生成提示词Prompt要求模型生成多样化、互补的查询。并行检索Parallel Retrieval将生成的N个查询同时或异步发送到向量数据库进行检索每个查询独立返回一个Top-K的文档列表。结果融合与重排序Result Fusion Reranking应用RRF算法对所有NK个候选文档进行去重和融合排序生成一个最终的、统一的Top-M文档列表M通常小于NK。答案生成Answer Synthesis将原始查询和融合后得到的最终上下文文档一起提交给LLM生成最终答案。整个流程强化了RAG的“检索”环节使其更加健壮和全面代价是增加了LLM的调用次数生成查询和检索次数属于一种“以计算换质量”的权衡策略。3. 关键实现细节与代码级解析3.1 查询生成的Prompt工程实战查询生成的质量直接决定了多路召回的效果。原项目提供了一个基础的Prompt但在实际使用中必须对其进行精细调优。以下是我经过多次实验后总结的一个强化版Prompt模板query_generation_prompt 你是一个专业的搜索引擎优化专家和信息检索助手。你的任务是为用户输入的问题生成多个不同的搜索查询以便从文档库中检索到最全面、最相关的信息。 原始问题{original_query} 请生成 {num_queries} 个搜索查询。这些查询应满足以下要求 1. **多样性**从不同角度、不同抽象层次切入问题。包括概念性提问、具体方法提问、问题诊断、解决方案对比等。 2. **互补性**生成的查询集合应能覆盖原始问题的各个方面避免语义重复。 3. **检索友好**查询应是完整的、语法正确的句子或短语包含可能出现在相关文档中的关键术语和同义词。 4. **长度控制**每个查询长度建议在5到15个词之间。 请直接输出查询列表每行一个无需编号和其他说明。 实操心得角色设定“SEO专家”或“领域专家”的角色设定能有效引导LLM生成更专业、更贴近文档风格的查询。数量控制num_queries通常设置在3-5个之间。太少则多样性不足太多则成本剧增且可能引入噪声。我的经验是4个是一个性价比很高的选择。指令明确明确要求“多样性”、“互补性”和“检索友好”是关键。我曾尝试不加这些指令结果LLM经常生成一些仅是句式微调如把疑问句改成陈述句的查询效果大打折扣。输出格式要求“每行一个”的纯文本输出极大简化了后续的解析代码避免处理JSON或标记语言可能带来的解析错误。3.2 RRF融合算法的实现与优化原项目的RRF实现简洁明了但我们可以对其进行优化增加健壮性和日志功能便于调试。def reciprocal_rank_fusion(search_results_list, k60): 对多个检索结果列表进行倒数排序融合。 参数 search_results_list: list of lists. 每个子列表是一个查询的检索结果每个元素是(document_id, score, metadata)。 k: 平滑常数。 返回 fused_results: 按RRF分数降序排列的列表元素为(document_id, rrf_score)。 from collections import defaultdict # 使用字典记录每个文档在所有列表中的排名 doc_rankings defaultdict(list) # 遍历每个查询的结果列表 for query_idx, single_query_results in enumerate(search_results_list): # single_query_results 应已按相似度分数降序排列 for rank, (doc_id, _, _) in enumerate(single_query_results, start1): doc_rankings[doc_id].append(rank) # 计算每个文档的RRF分数 rrf_scores {} for doc_id, ranks in doc_rankings.items(): score sum(1.0 / (k rank) for rank in ranks) rrf_scores[doc_id] score # 按RRF分数降序排序 fused_results sorted(rrf_scores.items(), keylambda x: x[1], reverseTrue) return fused_results # 优化点增加详细日志 import logging logging.basicConfig(levellogging.INFO) def reciprocal_rank_fusion_with_logging(search_results_list, k60, top_n50): fused_scores defaultdict(float) all_docs set() for i, results in enumerate(search_results_list): logging.info(f处理第{i1}个查询的{len(results)}条结果...) for rank, (doc_id, score, meta) in enumerate(results, 1): all_docs.add(doc_id) rrf_contribution 1.0 / (k rank) fused_scores[doc_id] rrf_contribution # 可选记录详细贡献用于深度调试 # if doc_id 某个特定文档ID: # logging.debug(f 文档 {doc_id} 在查询{i}中排名{rank}, 贡献 {rrf_contribution:.4f}) sorted_docs sorted(fused_scores.items(), keylambda x: x[1], reverseTrue)[:top_n] logging.info(f融合完成。共处理{len(all_docs)}个唯一文档返回Top-{top_n}。) return sorted_docs关键解析输入结构search_results_list的每个子列表应已按相似度分数从高到低排序。这是RRF算法正确工作的前提。去重defaultdict自动处理了文档去重。一个文档只要在任何一个列表中出现就会被计入。分数计算核心就是一行循环求和sum(1.0 / (k rank) for rank in ranks)。这里ranks列表记录了该文档在所有查询结果中的排名。k值影响当k很大时1/(krank)对排名的变化不敏感融合结果更倾向于“出现即可”当k很小时排名靠前如第1、2名的文档权重会被急剧放大。对于大多数通用场景保持k60是安全的起点。3.3 与向量数据库及LLM的集成策略rag-fusion本身是一个流程框架不绑定特定的向量数据库或LLM。这带来了灵活性也带来了集成的工作量。以下是我将它与ChromaDB向量库和OpenAI APILLM集成的核心代码片段import openai from chromadb import Client, Settings import asyncio import aiohttp class RAGFusionPipeline: def __init__(self, chroma_client, collection_name, openai_api_key, embedding_modeltext-embedding-3-small): self.chroma_client chroma_client self.collection self.chroma_client.get_collection(collection_name) self.embedding_model embedding_model openai.api_key openai_api_key async def generate_queries_async(self, original_query, num_queries4): 异步生成查询变体 prompt query_generation_prompt.format(original_queryoriginal_query, num_queriesnum_queries) try: response await openai.ChatCompletion.acreate( modelgpt-3.5-turbo, messages[{role: user, content: prompt}], temperature0.7, # 适当调高温度以增加多样性 max_tokens150, ) generated_text response.choices[0].message.content.strip() queries [q.strip() for q in generated_text.split(\n) if q.strip()] # 确保数量不足则用原始查询补足 while len(queries) num_queries: queries.append(original_query) return queries[:num_queries] except Exception as e: logging.error(f生成查询时出错: {e}) # 降级策略返回包含原始查询的简单变体 return [original_query] [f{original_query} 详细解释] [f{original_query} 方法] * (num_queries - 2) async def parallel_search_async(self, queries, top_k_per_query5): 并行执行向量检索 async def search_single_query(query): # 生成查询向量 query_embedding await self._get_embedding_async(query) # 执行搜索 results self.collection.query( query_embeddings[query_embedding], n_resultstop_k_per_query, include[metadatas, documents, distances] ) # 格式化结果 (doc_id, distance, metadata) # 注意Chroma返回的是距离相似度分数通常用 1 - distance 近似 doc_ids results[ids][0] distances results[distances][0] metadatas results[metadatas][0] formatted_results [] for i, doc_id in enumerate(doc_ids): # 将距离转换为相似度分数假设使用余弦距离值域[0,2]越小越相似 # 这里进行一个简单转换score 1 - (distance / 2)使其大致在0-1范围 normalized_distance distances[i] / 2.0 if distances[i] 2.0 else 1.0 score 1.0 - normalized_distance formatted_results.append((doc_id, score, metadatas[i])) return formatted_results # 并发执行所有查询的搜索 tasks [search_single_query(q) for q in queries] all_results await asyncio.gather(*tasks, return_exceptionsTrue) # 处理可能的异常 valid_results [] for res in all_results: if isinstance(res, Exception): logging.warning(f单个查询检索失败: {res}返回空列表) valid_results.append([]) else: valid_results.append(res) return valid_results async def _get_embedding_async(self, text): 异步获取文本嵌入向量 # 使用OpenAI Embedding API response await openai.Embedding.acreate( modelself.embedding_model, inputtext ) return response[data][0][embedding] async def run_fusion(self, original_query, final_top_k10): 运行完整的RAG-Fusion流程 # 1. 生成查询 generated_queries await self.generate_queries_async(original_query) logging.info(f生成的查询变体: {generated_queries}) # 2. 并行检索 all_search_results await self.parallel_search_async(generated_queries) # 3. 融合排序 fused_ranked_docs reciprocal_rank_fusion_with_logging(all_search_results, k60, top_nfinal_top_k) # 4. 获取最终上下文文档 final_doc_ids [doc_id for doc_id, _ in fused_ranked_docs] # 这里需要根据doc_ids从数据库获取完整的文档内容 final_contexts self._retrieve_documents_by_ids(final_doc_ids) # 5. 构建最终Prompt调用LLM生成答案此处省略具体Prompt构建 final_answer await self._generate_answer_async(original_query, final_contexts) return { original_query: original_query, generated_queries: generated_queries, fused_doc_ids: final_doc_ids, final_answer: final_answer } def _retrieve_documents_by_ids(self, doc_ids): 根据ID列表获取文档内容示例需根据实际DB调整 # ChromaDB可以通过get接口 results self.collection.get(idsdoc_ids) return results[documents]集成要点异步化查询生成和多个检索之间没有依赖关系非常适合用asyncio并发执行可以显著降低整体延迟。我实测下来对于4个查询异步并行相比串行耗时能减少60%以上。错误处理在生成查询或检索单一路径失败时必须有降级策略。例如生成查询失败则退回使用原始查询某一路检索失败则返回空列表不影响其他路径。这保证了系统的鲁棒性。分数归一化不同向量数据库返回的“距离”或“分数”含义和范围可能不同。在融合前RRF算法并不需要这些分数它只关心排名。但在调试和日志记录时一个归一化的相似度分数有助于理解。上面的代码展示了一种针对余弦距离的简单归一化方法。资源管理并行检索会同时向向量数据库发起多个请求需确保你的数据库连接池或服务能够承受这样的并发负载避免被限流或击垮。4. 性能调优与效果评估实战4.1 关键超参数实验与调优指南部署rag-fusion不是一劳永逸的以下几个超参数对最终效果和成本有决定性影响必须进行系统性的调优实验。参数含义默认/起始值调优方向与影响我的推荐num_queries生成的查询变体数量4数量 vs. 质量 vs. 成本增加数量能提高召回率但会增加LLM调用和检索成本并可能引入更多噪声。从3开始测试根据任务复杂度增至5或6。对于开放域问答4-5个是甜点。top_k_per_query每个查询检索的文档数量5检索深度增加此值能为融合提供更多候选文档但也会增加后续融合计算量和上下文长度。通常5-10足够。如果你的文档块很小可以增加到10-15。final_top_k融合后保留的最终文档数量10上下文窗口决定了最终提供给LLM的上下文量。受LLM上下文长度限制。根据LLM的上下文窗口和文档平均长度计算。例如GPT-4 Turbo 128K上下文可以设置得大一些如20-30。k (RRF常数)RRF算法中的平滑因子60排名权重锐度k值越小排名靠前的文档优势越大k值越大排名影响越平滑。除非有明确证据否则建议保持60。在查询数量很少如2个时可尝试调小至30。temperature (生成)生成查询时的LLM温度0.7查询多样性温度越高生成查询的随机性、创造性越强但也可能偏离主题。0.6-0.8是比较安全且能保证多样性的范围。对于严谨领域可降至0.3。调优方法建议构建一个小型的评估数据集50-100个问答对固定其他参数每次只调整一个参数评估最终答案的准确性可以用GPT-4做裁判评分。记录成本Token消耗、延迟和效果找到最适合你应用场景的平衡点。4.2 效果评估不仅仅是准确率评估rag-fusion不能只看最终答案的准确率还需要关注检索环节的改进因为这是它的核心价值。检索召回率RecallK提升这是最直接的指标。对比使用单一查询和rag-fusion多查询在相同的最终Top-K文档中能包含多少“标准答案”所需的参考文档。在我的一个技术文档问答项目中召回率从65%提升到了85%以上。答案相关性与完整性人工或使用更高级的LLM如GPT-4评估生成答案的相关性、信息完整性和是否包含来自多个来源的细节。rag-fusion的答案往往更全面能整合不同文档侧重点的信息。对模糊查询的鲁棒性专门测试那些表述不清晰、包含俚语或高度简化的用户查询。观察rag-fusion生成的查询变体是否能够“翻译”或“扩展”出更规范的检索语句从而找到相关文档。成本与延迟分析成本主要增加在“查询生成”的LLM调用上。例如用GPT-3.5生成4个查询大约消耗200-300 tokens。这需要与因答案质量提升带来的用户价值进行权衡。延迟由于并行检索检索阶段的延迟增加不多主要取决于数据库并发性能但增加了查询生成的LLM调用时间。总体延迟大约是基础RAG的1.5到2倍。通过异步优化可以将其控制在可接受范围内。实操心得不要盲目追求最高的召回率。有时候rag-fusion可能会召回一些相关但并非最核心的文档如果最终答案生成环节的Prompt没有很好的“信息筛选”能力反而会导致答案变得冗长或偏离重点。因此融合后的重排序RRF和最终答案生成的Prompt设计必须协同优化。我通常在给LLM的最终Prompt中会加入指令“请基于以下上下文优先采用最相关、最权威的信息来回答问题对于次要或背景信息可以简要提及。”5. 生产环境部署的挑战与解决方案5.1 处理大规模文档库的检索效率当文档库达到百万甚至千万级别时并行发起多个向量检索查询可能会对数据库造成压力。我的解决方案是查询路由与索引分区在生成多个查询后可以先用一个轻量级分类器或基于关键词的路由规则判断这些查询最可能属于哪个文档子集索引分区然后只在该分区内进行检索。这能大幅减少搜索空间。限制检索并发数虽然使用了异步但向向量数据库发起的并发连接数需要根据数据库的服务能力进行限制。可以使用asyncio.Semaphore来控制最大并发数。缓存层对于频繁出现的、或经过标准化后的查询变体及其检索结果可以引入缓存如Redis。特别是“查询生成”这一步对于相同或高度相似的原始查询可以直接使用缓存的变体列表避免重复调用LLM。5.2 降低LLM调用成本的策略成本是rag-fusion能否大规模应用的关键。使用小型/本地模型生成查询查询生成任务对模型的要求低于最终答案生成。可以尝试使用更便宜的模型如GPT-3.5-turbo而非GPT-4甚至部署在本地的小参数开源模型如Llama 3 8B, Qwen2.5 7B。只要模型具备基本的理解和改写能力即可。动态决定是否使用Fusion并非所有查询都需要多路召回。可以设计一个简单的过滤器对于非常简短、明确或之前已经验证过单一查询效果很好的问题跳过查询生成步骤直接使用原始查询进行检索。这需要对历史查询日志进行分析。批量处理对于离线或非实时性要求高的场景如知识库批量增强可以将多个用户查询收集起来批量调用LLM生成查询变体利用API的批量处理功能来降低成本。5.3 与现有RAG系统的无缝集成大多数团队已经有一套成熟的RAG系统。集成rag-fusion的最佳实践是将其模块化作为一个可插拔的“增强检索器”存在。# 假设你已有的基础RAG检索器 class BaseRetriever: def retrieve(self, query, top_k): # ... 原有的检索逻辑 pass # 增强版Retriever class FusionEnhancedRetriever(BaseRetriever): def __init__(self, base_retriever, query_generator, fusion_algorithmreciprocal_rank_fusion): self.base_retriever base_retriever self.query_generator query_generator self.fusion fusion_algorithm async def retrieve(self, original_query, top_k): # 1. 生成查询变体 generated_queries await self.query_generator.generate(original_query) # 2. 并行检索复用base_retriever all_results await self._parallel_retrieve(generated_queries) # 3. 融合 fused_results self.fusion(all_results) return fused_results[:top_k] async def _parallel_retrieve(self, queries): # ... 并发调用 self.base_retriever.retrieve pass这样你可以在不重写核心业务逻辑的情况下通过替换一个Retriever组件来升级系统。同时可以方便地进行A/B测试对比基础检索器和增强检索器的效果。6. 常见问题排查与实战避坑指南在实际部署和调试rag-fusion过程中我遇到了不少坑这里总结一份速查表。问题现象可能原因排查步骤与解决方案生成的查询变体质量差语义重复。1. Prompt指令不够明确。2. LLM温度参数过低。3. 原始查询本身过于简单或模糊。1. 强化Prompt中的“多样性”和“互补性”要求并给出具体例子。2. 将temperature提高到0.7-0.9。3. 对于模糊查询可以先让LLM对其进行一次澄清或重写再基于重写后的查询生成变体。融合后的结果似乎不如单一查询的最佳结果。1. RRF常数k设置不当。2. 某个查询变体检索到了大量无关文档拉低了优质文档的排名。3. 最终返回的文档数量final_top_k太少。1. 尝试调整k值先尝试调小如30。2. 检查每个查询变体的检索结果剔除那些明显跑偏的查询。可以在生成查询后加入一个简单的相关性过滤。3. 增加final_top_k给融合算法更多选择空间。系统延迟明显增加用户体验下降。1. 查询生成和多次检索串行执行。2. 向量数据库并发处理能力不足。3. 网络延迟。1.必须使用异步asyncio并发执行检索。2. 检查数据库监控考虑扩容或优化索引。3. 为所有外部服务调用LLM API, 向量DB设置合理的超时如5-10秒。答案变得冗长或包含矛盾信息。1. 融合后上下文包含过多或矛盾的文档。2. 最终答案生成的Prompt没有做好信息整合指令。1. 在融合后可以引入一个轻量级的重排序模型如Cohere Rerank, BGE Reranker对Top-M结果进行精排确保最相关的在最前面。2. 在最终Prompt中明确要求“请综合以下信息给出一个清晰、一致、无矛盾的答案。如果信息有冲突请以[某特定来源]或最新信息为准。”在特定领域如法律、医疗效果不佳。1. 通用的LLM如GPT-3.5生成的查询变体缺乏领域术语。2. 领域文档的表述与通用查询差异大。1. 使用领域数据微调过的模型来生成查询或在Prompt中提供领域术语表。2. 考虑在检索前对用户查询和生成查询都进行查询扩展加入同义词和领域特定表述。一个关键的避坑点不要忽视原始查询本身。在融合最终结果时我最初的做法是只使用生成的查询变体进行检索。后来发现有时原始查询本身就是最精准的。更好的做法是将原始查询也加入待检索的查询列表。也就是说如果你生成4个变体那么实际用于检索的应该是“原始查询 4个变体”共5个查询。这样可以确保最直接的匹配路径不被丢弃相当于给系统加了一个可靠的“保底”策略。经过几个月的迭代rag-fusion已经成为我们生产RAG系统中不可或缺的一环。它带来的召回率提升是实实在在的尤其对于复杂、开放域的问答场景。其核心价值在于它用一种相对简单优雅的方式将LLM的语义理解能力注入到检索的前端打破了传统RAG检索环节的“语义孤岛”。当然它引入了额外的复杂性和成本这就需要我们根据具体的应用场景在效果、速度和成本之间做出精明的权衡。我的建议是先从最重要的或效果瓶颈最明显的查询场景开始试点用数据证明其价值后再逐步推广。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2582099.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…