AICon上海「Agent与多模态解决方案专场」火热来袭!即刻报名,与创新同行~ 了解详情
写点什么

领域驱动的 RAG:基于分布式所有权构建精准的企业知识系统

作者:George Panagiotopoulos

  • 2025-05-19
    北京
  • 本文字数:7678 字

    阅读完需:约 25 分钟

大小:3.82M时长:22:15
领域驱动的RAG:基于分布式所有权构建精准的企业知识系统

我们的背景

作为一家在银行技术领域拥有超过 30 年行业经验的领军供应商,我们拥有丰富且极具创新性的代码库,并通过战略性收购不断扩大业务。多年来,我们一直将自己定位为行业的创新者,但创新的迅猛步伐也为我们带来了在庞大产品线中保持文档一致性与时效性的挑战。


虽然我们代码库的部分模块拥有坚实且管理得当的文档,但仍有部分模块存在文档不清晰或内容过时的问题,这导致我们的销售工程师和客户架构师很难找到所需的信息。此外,我们的领域专家在各自的专业领域拥有深厚的知识和丰富的经验,但这些宝贵的专业知识往往分散且孤立,难以被系统地整合和获取。


此前,我们曾尝试通过知识共享计划和培训项目来解决这一问题,但由于文档分散和专业知识孤立,这些努力的效果并不理想。我们还尝试引入基于静态预定义问题和答案数据库的事实查找工具。然而,这些工具在使用过程中面临一个重大挑战——缺乏上下文信息。通常情况下,如果问题本身或其上下文(或两者)稍有不同,针对特定问题在特定上下文中的答案就难以复用。为了克服这些获取准确技术信息的障碍,我几个月前决定探索使用检索增强生成(RAG)技术。我们的领域专家开发了这个辅助工具,旨在帮助团队提升事实查找的效率。


RAG 是一种新兴的 AI 技术,融合了检索和生成模型,旨在提升事实查找的准确性和效率。通过将智能搜索引擎与 AI 生成的响应相结合,RAG 系统能够访问庞大的数据源,提供准确且高效的答案。这种整合能够处理复杂查询,提供实时更新,并支持多种语言。目前,基于大语言模型(LLM)的技术(如 RAG)存在准确度低和模型容易出现“幻觉”的问题,即生成错误或虚构的信息。尽管在提升系统可靠性方面已经取得了一定进展,但可靠性仍然无法达到人类水平。有趣的是,我们的人类顾问目前的“幻觉”程度低于 AI 模型,这听起来既好笑又发人深省。


为了保持人类的优势并确保最高标准的准确性,我们严格地将 AI 定义为一种咨询工具。这意味着应用程序只是作为工具,协助顾问查找信息,顾问需要负责过滤、验证和修改 AI 生成的输出,以确保结果的正确性和完整性。尽管目前市场对自主智能体的热情很高,但我们清楚地认识到,AI 技术尚未成熟到可以被用在关键业务上的程度。

知识所有权

为了应对这些挑战,我们正在重新分配销售工程团队对 RAG 实施的所有权。鉴于产品线的复杂性和维护一致性文档的难度,我们意识到仅靠集中式管理是不够的。因此,我们决定指定专门的领域所有者——即安插到特定团队的专家——来负责监督 RAG 系统在其各自领域的集成和微调。


这些领域所有者的任务是确保 RAG 系统能够无缝对接其团队的独特需求,同时保证响应的准确性。每位领域专家将利用自己的 AI 基础设施优化搜索参数和系统提示词,以适应各自领域的细微差别。


例如,一位所有者可能会专注于从各个角度(包括功能架构、应用架构、部署等)了解特定产品的运作方式,而另一位负责构建 SaaS RAG 应用的所有者则会花费更多时间确保应用程序能够准确满足我们的服务等级协议(SLA)和默认服务设置。除了技术调整外,这些所有者还需要负责高质量的文档和培训材料,确保其团队能够高效利用 RAG。


系统提示词工程是领域所有者的核心职责。他们负责设计、测试和优化这些提示,以确保 RAG 系统能够在其特定领域中准确理解查询。通过反复迭代测试,所有者开发出能够引导大语言模型检索最相关的信息并且生成为团队应用场景进行了适当格式化的响应的提示词。


这种专业化的提示词工程需要深厚的专业知识和大量的实验,因为提示词中的细微措辞变化都可能会显著提高准确性。通过控制系统提示词,所有者有效地“调整”了 RAG 应用,使其适应各自领域的术语、优先事项和常见问题模式,从而创建了一个更可靠且更具情境感知能力的信息检索系统。


这种方法充分利用了领域专家深厚的专业知识,同时结合了 AI 驱动解决方案的效率。通过分配所有权,我们正在创建一个系统,让人类洞察力和机器学习协同工作,共同应对每个产品线独有的挑战。这种协作不仅提高了 RAG 输出的准确性,还能确保我们的团队能够应对现代银行技术不断变化的需求。


使用元数据现在有一种趋势是将所有可用知识直接传给具有大上下文窗口的大语言模型,尽量减少 RAG 的使用。一些研究人员声称这种方法更好。然而,我的实验以及一些在线研究都表明,情况并非总是如此。当上下文窗口包含了大约五十万个 Token 时,大语言模型的准确性会显著下降(注意,这个数字会随着时间发生变化)。你可以参考这一领域的许多研究(例如,文章《长上下文与 RAG:对大语言模型的评估与重新审视》和《检索增强生成还是长上下文大语言模型?》)。


我们尝试将所有 RAG 助手的文档传给具有数十万 Token 上下文窗口的大语言模型,结果并不如使用 RAG 获得的结果好。此外,这种做法导致成本大幅增加(尽管大语言模型的价格持续下降,但至少在可预见的未来,成本仍将取决于所使用的 Token 数量)。因此,我们决定转向基于元数据的方法。


我们目前采用特定的方法来生成元数据。首先,我们将 RAG 文档传给标准的大语言模型。我们要求大语言模型“总结文档,重点描述文档所包含的信息的类型”。然后,我们的领域专家会评审和编辑大模型的输出内容,使其更精准地反映文档内容。元数据还包含了该领域常用的几个关键词,这些关键词可能是常用的三字母缩写、内部项目名称,或者是与当前或过往使用过的等效组件相关的旧名称。


元数据是 RAG 应用中组织和提供上下文信息的核心,帮助用户理解系统响应的范围和背景。在银行技术领域,管理多样化的产品线和服务需要精确的信息检索,这种结构化的方法显得尤为重要。

解决 RAG 的伸缩性问题

在解决 RAG 系统伸缩性问题时,我们探索了三种主要方法。首先,允许用户同时搜索所有应用,这种方法虽然简单,但随着应用数量的增加,效率逐渐降低。由于缺乏针对性,这种方法在面对更大、更复杂的系统时,准确性问题愈发明显,难以满足需求。其次,我们尝试利用元数据根据用户查询自动选择最相关的 RAG 应用,这是一种更具针对性和高效的方法。


通过将查询传给可与元数据匹配的大语言模型,可以精准识别出最合适的 RAG 助手。这种方法提高了精确度,尤其是与手动选择规则结合使用时。例如,如果用户的问题包含特定产品的名称,系统会将查询定向到该产品的 RAG 应用。第三,允许用户手动选择助手,这在用户清楚自己需要什么样的帮助时非常有用。这种方法有效补充了自动分类过程,在可能存在多个相关应用的情况下尤为有效。


展望未来,我们计划允许自动分类器识别出匹配度最高的两到三个助手。然后,用户可以在这些选定的应用中进行搜索,随着 RAG 应用数量的增加,这种方法将显著提升搜索效率。这一改进将有助于管理我们多样化的产品组合,确保用户能够快速获取准确且相关的信息,满足他们的需求。


上述方法为用户提供了更大的灵活性,以便组合和选择合适的资源。下图展示了我们应用程序的概貌。


图 1:具有分布式所有权的 RAG 应用

从设计到实现

在确定了元数据策略和分布式所有权模型后,我们需要将这些概念转化为一个可供团队日常使用的功能性应用。这需要将理论上的 RAG 概念付诸实践,构建一个完整的工具,将其整合到我们现有的工作流中,并实现我们独有的知识检索方法。

实现方法:构建一个完整的应用

RAG 实现

我们的 RAG 应用并非只是一个基础的 AI 查询系统,而是一个致力于提升用户体验并确保高信息准确性的综合性应用。我们使用 Flask 构建了一个标准的 Web 应用,具备身份验证机制、错误处理能力和响应式用户界面。这让我们能够专注于整合 RAG 功能,而无需从头构建基本的应用基础设施。


我们的应用基于一个分布式 RAG 系统,由各领域所有者管理专属的知识模型。每个模型独立运行,拥有自己的向量存储,其中包含了特定领域的文档。这种架构实现了信息检索的精细化管理,并保留了前面所描述的分布式所有权模型。


在此,详细阐述我们目前对知识模型的定义或许能提供更清晰的视角。目前,我们的知识模型由以下四个核心组成部分构成:


1.我们精选的文档的向量存储。


2.前面部分描述的元数据,用于定义每个 RAG 应用所涵盖的领域。


3.系统提示词,可用于格式化响应,使其严格遵循我们的品牌指南,同时突出不同组件的业务优势。最重要的是,系统提示词能够有效防止“幻觉”,确保 RAG 应用只根据提供的材料生成响应,而不进行推断或加入行业的标准知识。


4.描述解决方案组件的 UML 图。我们目前使用类图来表示解决方案组件,并且最近在探索使用序列图来帮助 RAG 应用理解流程。除了直接将 UML 文件包含在向量存储中,我们还生成 UML 图的文本描述(这些描述同样是在设计阶段利用大型语言模型生成的)。


图 2:每个 RAG 应用都有自己的知识模型


我们主要实现了三种查询路径,与我们的元数据策略紧密契合:


1. 自动选择模式利用了智能问题分类器,根据内容分析将查询路由到最合适的知识模型。这个分类器结合了基于规则的模式匹配(用于处理显而易见的查询场景)和基于大语言模型的分类系统(用于应对更复杂、更微妙的查询需求)。


def classify_question(question):    # First, apply rule-based pattern matching for common topics    if any(re.search(r'\b' + re.escape(term) + r'\b', question, re.IGNORECASE)            for term in ["payment", "payments", "payment hub"]):        return "Payments"        # For more complex questions, use LLM classification    llm = AzureChatOpenAI(        deployment_name=os.getenv("AZURE_OPENAI_DEPLOYMENT"),         temperature=0    )    combined_prompt = f"{system_prompt}\n{definitions_prompt}\n\nQuestion: '{question}'\nCategory:"    response = llm([{"role": "user", "content": combined_prompt}])    return extract_category(response)
复制代码


该分类器首先应用模式匹配,快速识别常见主题,然后回退到大语言模型进行更细致的分类,缩短了处理时间,同时确保复杂查询的准确性。


2. 在手动选择模式下,用户可以选择要查询哪个领域的知识模型。如果他们清楚知晓答案所在的领域,这一模式为他们提供了精准的控制能力。


3. 全部搜索模式使用了集成检索器,在所有知识模型中进行全面搜索,当用户不确定具体领域时,能够检索更广泛的信息。我们的 API 端点可以处理这三种模式,对查询进行适当的路由:


@app.route('/api/auto-classify', methods=['POST'])@auth.login_requireddef auto_classify():    data = request.json    query = data['query']    mode = data.get('mode', 'auto')        try:        if mode == 'auto':            # Use the classifier to determine the appropriate model            category = classify_question(query)            component = component_mapping.get(category)            response = RAG_MODEL_FUNCTIONS[component](query)            formatted_response = response.get('result', str(response))                    elif mode == 'search_all':            # Query all models using ensemble retriever            response = get_all_model_response(query)            formatted_response = response.get('result', str(response))                    else:            # Manual selection (component specified in request)            component = data['component']            response = RAG_MODEL_FUNCTIONS[component](query)            formatted_response = response.get('result', str(response))                    return jsonify({            'component': component if mode != 'search_all' else 'AllModels',            'query': query,            'response': formatted_response        })    except Exception as e:        return jsonify({'error': f"Error processing query: {str(e)}"}), 500
复制代码


这个端点根据选定模式动态路由查询,实现了我们的元数据驱动的方法,展现了我们如何将分类、手动选择和全面搜索功能进行有机的整合。

使用 UML 增强知识表示

为了提供超越简单文本响应的用户体验,我们整合了 UML 图可视化功能。用户可以通过交互式图表探索组件之间的关系,为他们的查询提供架构上下文信息。更重要的是,我们将这些图表作为 RAG 应用的知识来源。


我们的 UML 文件包含了描述性文本属性,因此成为大语言模型有价值的输入来源。例如,以下代码片段就来自我们的集成层图表:


package "Integration Layer" {    class PubSubBroker {        + Type: Kafka / Azure Event Hub        + Purpose: Event-driven communication    }    class MQBroker {        + Type: ActiveMQ        + Purpose: Event-driven communication    }    class APIGateway {        + Type: API Gateway        + Purpose: Routes and manages API requests    }    class SFTP {        + Type: SFTP client/server        + Purpose: File exchanges    }    class GIT {        + Type: Source Control Management        + Purpose: Source Control, entry point to DevOps    }}
复制代码


这种结构化的表示包含了组件类型和用途等关键属性,我们将这些属性解析并转换为描述性文本文件。然后,这些文件与原始 UML 文件一起被放入我们的 RAG 知识库。在转换过程中,我们保留了层次关系和技术细节,将图形连接转化为系统交互的文本描述。


我们配置了系统提示词,为来自这些基于 UML 的知识源的答案赋予更高的置信度,尤其是在处理架构和集成相关问题时。当用户询问有关系统组件的问题时,RAG 应用能够有精确文档支撑的详细答案,而不只是泛泛而谈的一般性知识。


目前,我们在知识库中同时使用了类图和序列图。类图提供系统组件及其相互关系的结构化信息,而序列图提供对流程和交互模式的见解。这种组合使我们的 RAG 应用能够全面掌握系统的静态架构和动态行为。


随着不断优化我们的方法,我们也在探索丰富 UML 文件内容的方式,增加更多的描述性文本,例如为每个组件添加详细注释,这些注释可以被大语言模型处理,而不会影响图表的视觉表示。通过这种方式,领域专家将更深入的知识直接嵌入到架构文档中,使得信息既能以直观的视觉形式供人类使用,又能以文本形式供我们的 RAG 应用进行分析和处理。

应用架构和管理

系统有身份验证机制,具备日志记录功能和错误处理能力,确保了系统的安全性和可靠性。我们遵循标准的 Web 应用实践,实现了输入验证、路径遍历预防和安全凭证管理。凭借这种强大的基础设施,领域专家可以全身心地专注于知识策划工作,无需为应用安全问题分散精力。


我们的后端采用了单例模式来管理 RAG 应用,确保可以高效利用资源,同时保持不同向量存储之间的分离。这种设计可以可以确保系统在随着更多领域专家创建专属知识模型时进行水平扩展,而不会增加额外的内存占用。


系统提示词通过一个集中式的配置系统进行管理,领域所有者可以自定义提示词,让他们能够控制大语言模型如何解释检索到的信息。这种方法使得领域专家能够在不修改代码的情况下调整知识来源和响应风格。


Web 界面提供了一个直观的仪表盘,用户可以:

  • 提交查询并选择他们偏好的搜索模式;

  • 通过 UML 图可视化技术架构;

  • 将多个组件组合成全面的架构视图;

  • 无缝访问基于 RAG 的知识和结构化文档。


我们构建了一个完整的软件应用,而不仅仅是一个 AI 接口,并将它整合到我们团队的工作流程中,同时保留了确保信息准确性和相关性的分布式所有权模型。

性能评估

方法论

在进行初步评估时,我们希望知道模型在多大程度上能够满足我们的准确度要求。


我们实现了双管齐下的评估方法:


  • 基于分类器的路由。

问题由基于大语言模型的分类器处理,确定应该由哪个模型处理查询。


  • 全面覆盖。

同样的问题同时由所有可用的模型处理。


对于每个问题,我们记录了分类器的路由决策以及每种方法所生成的答案。然后,人类专家根据四个关键指标对输出进行评估。

评估指标

我们的评估框架采用了四个互补的指标:


指标

描述

公式

分类器准确性(81.7%)

衡量分类器将问题准确路由到适当模型的能力。

正确分类的问题数/问题总数

响应精确度(分类模型)(97.4%)

仅评估正确分类问题的答案质量。

正确分类问题中的优质答案数/正确分类问题总数

响应精确度(所有模型)(83.8%)

评估同时使用所有模型时的答案质量。

所有模型中的优质答案数/问题数总

专家引导的答案恢复率(63.4%)

确定人类专家是否能在任何一种方法中找到满意的答案。

两种方法中包含有用答案的问题数/问题总数


关于这些指标的简要说明:


在我们的评估过程中,当模型确实缺乏相关信息时,我们将“我无法对此发表评论”的回答视为正确答案,我们强调的是真实性而不是幻觉。正如前面提到的,我们更希望我们的专家每次都能找到正确的信息,而不是冒着出现不准确结果的风险。因此,当模型说“我不知道”时,这实际上是一个好答案——我们必须坚决避免提供错误的信息。我们希望模型能够坦诚地承认不确定性,并将进一步的调查工作交给人类专家。


因此,在评估响应精确度时,这些“我不知道”的情况被认定为积极的结果。但需要注意的是,“我不知道”的回答会为顾问增加手动工作量,他们随后需要通过传统方式自行查找答案。我们可以通过微调系统提示词和增强元数据来减少这种情况的发生。


第二个指标——专家引导的答案恢复率——衡量的是分类模型或所有模型能够直接正确回答的问题数量。这本质上反映了我们所实现的自动化程度。为了提升这一指标,我们可以通过为每个 RAG 应用注入更多知识来进一步增强其能力。

关键的发现

我们的分析揭示了几个重要的见解:


  • 分类质量至关重要。

尽管分类器正确路由问题的准确率达到了 81.7%,但总体响应精确度(包括错误分类时为 88.5%)与仅在正确分类时的响应精确度(97.4%)之间存在显著差距。这一差异表明,分类错误对答案质量有着显著的负面影响。


  • 专门模型优于全面查询。

当问题被正确分类时,针对性的模型方法(响应精确度为 97.4%)显著优于同时查询所有模型的方法(响应精确度为 83.8%)。这表明,专注于特定领域的知识检索能够产生更高质量的答案,相比更广泛但不够专注的方法更具优势。


  • 人类的监督仍然有价值。

专家引导的答案恢复率仅为 63.4%,这表明人类专家通常能够从任何一种方法中提取有用信息,这突显了在复杂的问答系统中人类判断的重要性。


图 3:性能评估指标

结论

我们的研究结果表明,提升分类器的准确性能够显著提高答案质量,从而带来显著的回报。当分类器正确地将问题路由到专门的模型时,其提供的答案精确度高达 97.4%,明显优于同时查询所有模型的方法。然而,响应精确度指标之间的差距凸显了继续改进分类系统的必要性。


对于部署了多个专门模型的 RAG 系统的组织而言,这些结果表明了一种混合策略:在置信度较高时使用分类器来路由问题,但在置信度较低或初始答案不满意时保留查询所有模型的能力。

总结与展望

我们的 RAG 实现方案通过分布式所有权模型、基于元数据的查询路由和增强的 UML 知识库,展现了一种独特的知识管理方法。将这些创新性元素整合到一个完整的应用中,我们打造了一个系统,不仅能够支持我们产品知识的复杂性和多样性,还能够高效地服务于我们的团队。


初步的结果令人振奋,我们的销售工程师反馈称,他们能够更快地获取到准确的信息,领域专家也对其在知识领域的掌控权表示满意。我们每天都在积极增强这个系统,改进 UML 解析能力、提高分类准确性并扩展知识库。我们在不断完善这个工具,致力于在 AI 辅助与人类专业知识之间保持最佳平衡,为我们的团队提供最高质量的信息,从而更好地服务于我们的客户。


【声明:本文由 InfoQ 翻译,未经许可禁止转载。】


查看英文原文https://www.infoq.com/articles/domain-driven-rag/

2025-05-19 11:43382

评论

发布
暂无评论

能源绿色管控:天然气站启动数字化转型,工业企业该如何突围?

一只数据鲸鱼

物联网 数据可视化 智慧城市 能源管理 天然气

力扣(LeetCode)刷题,简单题(第13期)

不脱发的程序猿

面试 LeetCode 28天写作 算法面经 3月日更

阿里面试官:Android开发真等于废人?已拿offer附真题解析

欢喜学安卓

android 程序员 面试 移动开发

2021最新分享三面百度提前批(Java开发岗)面经 已拿Offer

比伯

Java 编程 架构 面试 程序人生

透过 3.0 Preview 看 Dubbo 的云原生变革

阿里巴巴云原生

容器 运维 云原生 dubbo 应用服务中间件

C 语言性能优化:循环条件i<=n与i!=0的性能差异

1

行业资讯 | Android WebView 致安卓应用闪退,mPaaS 助你规避这波 Bug

蚂蚁集团移动开发平台 mPaaS

android webview mPaaS 离线包 UC内核

低代码是什么?低代码价值主要体现在哪?

优秀

低代码

从解决Github TimeOut到经典面试题:从输入URL到浏览器显示页面发生了什么?

秦怀杂货店

GitHub TCP 网络 HTTP DNS

python编译器中出现了绿色波浪线,光标放上去出现的提示是什么意思?

Emotion

为什么python中程序的结果会一直输出,需要怎么解决

Emotion

定义结构体访问结构成员的三种方法

Emotion

实习就参与“服务过亿用户的项目”,是什么体验?

阿里巴巴云原生

开发者 云原生 调度 应用服务中间件 Go 语言

LeetCode题解:92. 反转链表 II,迭代,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

实现跨生态互联,区块链赋能智能家居新体验

旺链科技

区块链应用 智能家居

程序员去大公司面试,小程序FMP优化实录,已拿offer入职

欢喜学安卓

android 程序员 面试 移动开发

被MySQL慢日志查询搞废了?3分钟教你快速定位慢查询问题!

观测云

云计算

Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题

阿里巴巴云原生

Java 微服务 云原生 seata Go 语言

困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞

不脱发的程序猿

28天写作 硬件设计 嵌入式软件 单片机 3月日更

字节抖音iOS客户端实习 123hr面 面经

iOSer

ios 字节跳动 面试 抖音

为了跳槽刷完1000道Java面试真题,没想到老板直接给我升职了

Java 程序员 架构 面试

OpenKruise 如何实现 K8s 社区首个规模化镜像预热能力

阿里巴巴云原生

Serverless 容器 云原生 k8s 调度

我在阿里实习做开源

阿里巴巴云原生

阿里巴巴 云原生 dubbo 个人提升 中间件

活动 | Apache Pulsar Meetup 欢迎报名

有道技术团队

活动

Go Storage存储包封装

非晓为骁

storage Go 语言

可能是绝唱!阿里资深工程师深度解读Netty底层核心源码

Java架构追梦

Java 源码 架构 面试 Netty

单账户实时记账能力达2万笔每秒 蚂蚁启用新一代高性能记账引擎

DT极客

这个GItHub上的Java项目开源了,2021最全的Java架构面试复习指南

Java 程序员 面试

区块链中药溯源--区块链为中医药溯源认证

13530558032

有道技术岗大揭秘!这么幸福的生活,真的是熬夜掉发Top1的职业吗?

有道技术团队

招聘

电子证照上链--助推智慧政务

13530558032

领域驱动的RAG:基于分布式所有权构建精准的企业知识系统_AI&大模型_InfoQ精选文章