为了账号安全,请及时绑定邮箱和手机立即绑定

基于法律条款的智能检索系统:多图多代理递归检索流程

作者:Timothy Chung,Chia Jeng Yang

最新消息:我们最近将知识图谱编辑器开源了,点击链接查看详情:https://medium.com/enterprise-rag/open-sourcing-the-whyhow-knowledge-graph-studio-powered-by-nosql-edce283fb341

在这篇文章和开源仓库中,我们希望通过一个利用词汇图(文档层次结构)和多图多代理流程中的块链接的多代理系统,来展示对法律文件条款的智能导航。我们在这里使用的栈是Reducto.AIWhyHow.AILanggraphLlamaIndex。您可以访问开源仓库这里

我们在处理文档,尤其是法律文件时遇到的一些具体问题之一,就是需要构建文档中的条款层级,以便理解文档中不同条款之间的相互引用。这是因为条款有时会引用其他条款来获得完整的意思和上下文。

为了理解整个背景,你需要递归查找并检索任何提到的条款(甚至包括脚注!),在文档结构中找到提到的内容,检查是否有提到其他内容并重复这个过程。递归检索不仅适用于法律文件,还可以应用于页码、图片等多模态数据,链接到其他文档或外部数据等元素。

我一直对法律文件很感兴趣,尤其是在图形遍历和检索方面,因为这些文件具有结构化的特性,这使得我对此非常感兴趣。在法律文件中,还有一个特定的结构化检索步骤,即定义页,在此页面中,每个具体的术语都有一个具体的、可以变化或固定的定义,这些定义会随着文件性质的不同而变化。

在这份笔记本和示例中,我们想展示的是如何轻松创建法律文件内各条款的层级文档图、定义的层级图,以及一个涉及多个代理的递归检索过程。该过程通过智能地在这些图之间导航,从而彻底回答针对该文件的问题。

在这个案例中,我们使用一份简单的监管文件,具体是这个文件:这份文档,该文件规定了各种组织的合规条例。

我们想回答的问题是:董事会和首席合规官如何管理控制功能?

回答这个问题的最好方式是:

  • 从定义页面给我提供CCO的定义内容
  • 从第6.3条和第7.2条中提取信息
  • 在第7.2条中检测到“参见第7.3和第7.4段”
  • 导航到第7.3和第7.4段并提取内容
  • 检测到提到第9.1段,并提取第9.1段内容

作为快速测试的基准,当我们用ChatGPT运行这个时,它使用的是GPT4o,自带代理推理功能,我们得到了以下回复:

董事会和首席合规官(CCO)对控制职能的管理涉及《合规文件》中概述的若干关键职责:

**董事会的职责:**
1. 负责监督合规风险管理:董事会负责监督金融机构内部合规风险的管理,包括批准合规政策、建立合规功能和任命首席合规官。
2. 支持合规功能:董事会必须确保合规功能和首席合规官拥有适当的权威和独立性,以有效履行其职责。董事会还必须确保合规功能得到充分资源支持。
3. 与首席合规官互动:董事会应定期与首席合规官互动,讨论合规职能面临的问题,并确保首席合规官可以直接接触董事会。
4. 年度评估:董事会必须至少每年评估机构管理合规风险的有效性,考虑高级管理团队、内部审计和首席合规官的意见。

**首席合规官(CCO)的职责:**
1. 合规风险的管理协调:CCO 负责协调合规风险的识别、管理和监控,确保合规监控和测试活动在组织内保持一致。
2. 报告与咨询:CCO 必须定期向高级管理团队报告合规风险的识别和分析,并确保报告随时可提供给内部审计和监管机构。CCO 还需向董事会和高级管理团队提供有关法律和监管要求的咨询,使其了解法律和监管要求的最新情况和影响。
3. 独立性:CCO 必须保持独立性,确保其职责、报告线路或报酬中没有利益冲突。
4. 资源与培训:CCO 必须确保合规功能充分配备了具备必要资格和经验的人员,并负责确保为相关人员提供充分的法律和监管要求培训。

**与其他控制职能的互动:**
合规职能的组织方式应考虑金融机构的规模、性质和复杂性,以便有效管理合规风险。当合规功能与其它控制功能共享职责时,需要有明确的文件记录和协调,以确保CCO能够有效履行职责而不影响其独立性和专注度。通过履行这些职责,董事会和CCO 可以确保机构的合规风险得到有效控制,支持金融机构的整体安全和稳健性。

这个回答虽然有趣,但还不够全面,因为它:

  • 看来它特别关注关键词“合规性”,并强调了所有与其它条款相关的合规义务,而不是专门针对董事会和合规官(CCO)。例如,不同地区的协调(第8.2段)是在“合规性”的背景下提出的,而薪酬的独立性(第7.8段)也是在“合规性”的背景下提出的。
  • 更重要的是,它似乎遗漏了第7.3和7.4段中的明确提及,这些段落明确规定了董事会和合规官之间的关键义务,即当合规官分享控制职能时,需要得到董事会的批准。它还遗漏了第9.1段,该段涉及审计职能和合规职能的分离。

可以理解这一点,因为递归检索条款、页面和页脚等内容并不是语义检索过程的一部分,而这些过程并不包含在RAG中。

我们开发的多代理工作流简介

希望了解每个代理具体功能的人,我们还在附录中提供了每个代理的代码示例。

创建图表

在这个笔记本里,我们首先提取由Reducto的解析的文档结构。文档结构将每一页拆分为不同的元素,比如:章节标题、列表项或页脚。

元素随后根据它们出现的顺序以及隐含的层级关系进行组合,例如,部分标题是列表项的父元素。接着我们分析文档中的链接,以识别这些提取元素之间的连接,这些连接可以建模到词汇图中。

链接文档层级/词汇图谱

我们使用我们的SDK here 将片段和三元组导入到WhyHow的知识图谱编辑器中,以创建词汇图谱。

我们还为这份文档构建了一个法律定义图表。在法律文件中,每个文档都会有一个定义部分,用于定义某些术语的特定解释方式。这可能因文档、使用场景或客户的不同而有所不同。在这种情况下,文档的定义部分位于第4至第5页。这些文本被提取出来,并作为提示传递给GPT-4o,要求它逐字提取法律术语及其定义,并返回结构化的输出。输出被转换为CSV文件,并使用SDK和预定义的模式上传为一个单独的图表。定义图表会在需要时被定义代理调用,以用特定的相关定义增强上下文。在这种情况下,在检索初始条款后定义代理会被调用。

定义图的链接

我们将WhyHow中的节点导入到笔记本中,并使用LlamaIndex对节点的信息进行本地索引,并保留了WhyHow生成的嵌入信息。我们结合使用了LlamaIndex的向量检索器、BM25检索器以及关键词检索器。在处理法律文档的应用场景中,BM25和关键词检索器的引入有助于提高在查询和检索过程中的术语准确性。BM25有助于在高度重复的文本中识别关键术语,而关键词检索器则确保即使出现频率较低的重要术语也能按需被检索到。

LangGraph 利用 WhyHow SDK 和 GPT-4o 构建了一个围绕词汇图的多代理工作流。本质上,当接收到一个查询时,系统首先通过初始搜索代理搜索相关的向量片段(在本例中为条款或子条款)。定义代理随后被调用来增强条款的相关定义。路由代理接着检查是否有链接的部分或脚注需要引用,并在必要时检索并考虑这些部分。如果检索到的条款引用了更多的条款(如本例所示),递归检索代理将继续进行检索。

我们先找到了第6.3和7.2这两条,然后查了一下定义部分,看看定义图中是否有需要包含的额外信息。此外,还包括对“CCO”和“高级管理层”的额外定义。

在第6.3段中,以下为6.3.f小节:

  • “当首席合规官(CCO)还承担其他控制职能3的职责时,确保整体控制环境不会因CCO承担的职责组合而不会受损。”

基于第一个子句的信息,路由代理帮助检测材料中是否有提及的子句或脚注。在这种情况下,第一个子句与脚注3相关联。随后,路由代理触发脚注解析代理。脚注解析代理识别相关的脚注并返回以下内容:

  • “请参阅第7.3和第7.4。”

在这里,需要进行另一次遍历操作,使用递归检索工具来遍历词汇图谱,并从第7.3和7.4段中检索片段或从句部分。

这里将7.3和7.4段落中的新信息结合在一起。其中,7.4(b)条款引用了9.1条款。

  • “合规职能的职责不能与内部审计职责共享,首席合规官也不能承担内部审计职责,因为这样做会让第9.1段描述的独立审查过程失去效力。”

第7.4段包含一个链接,指向第9.1段,路由代理检测到这个链接,并指示递归检索代理在下一次扫描时检索它。回答代理跟踪所有传入的信息,以进行总结,并最终形成返回给用户的答案。

最后答案构建符合我们理想的流程,并从条款定义页、第6.3段、第7.2段、脚注3、第7.3段、第7.4段和第9.1段中提取信息,通过智能遍历,为用户准确总结了所有相关信息。

为了确保我们不是仅仅靠运气,我们重复运行了最终的查询3次,每次都成功检索到了相关信息。

为了有效管理控制职能,董事会和首席合规官(CCO)有各自必须履行的责任:

**董事会的责任:**
- 批准关于首席合规官(包括任命、薪酬和解聘)的关键决策(第6.3(a)节)。
- 确保首席合规官具有足够的地位和影响力,能够与高级管理层有效互动(第6.3(b)节)。
- 定期与首席合规官讨论合规问题,并考虑在没有高级管理层在场的情况下进行讨论(第6.3(c)节)。
- 为首席合规官提供不受阻碍的直接与董事会沟通的渠道(第6.3(d)节)。
- 支持首席合规官获得足够的资源以有效履行职责,包括具备能力的工作人员(第6.3(e)节)。
- 确保任何合并的责任不会影响控制环境(第6.3(f)节)。

**首席合规官的责任:**
- 协调全机构范围内的合规风险识别和管理(第7.2(b)节)。
- 确保组织内合规监控和测试的一贯性和有效性(第7.2(b)节)。
- 即使在承担其他控制职能的情况下,也应保持独立性并专注于合规职责(第7.3节)。

**共享责任与协调:**
- 董事会应批准合规职能责任在合规部门与其他控制职能之间的共享(第7.4(a)节)。
- 职责范围及其沟通机制应明确并记录(第7.2(a)节)。
- 应建立有效的协调机制以支持首席合规官的职责履行(第7.2(d)节)。
- 合规职责不应影响内部审计职能的独立性(第9.1节)。

董事会应确保全面监督,首席合规官应维持组织内有效的协调和沟通,以高效地管理控制职能。

我们开发了一个系统,具备了以下特点。

  • 一个多图处理系统,每个图代表RAG系统中的不同功能和目标。
  • 使用Reducto、WhyHow和LlamaIndex创建具备RAG能力的自动化词汇网络。
  • 一个多代理系统,允许根据文档设计为让人类阅读和浏览的方式智能遍历文档,并以结构化方式从各部分和子部分返回答案。
  • 一个多图多代理系统,由LangGraph管理。

为什么WhyHow.AI的知识图谱工作室平台(KG Studio)(目前处于测试版阶段)是构建模块化知识图谱的最简单方式,结合了大型语言模型、开发者和非技术领域专家的工作流程。

如果你正在考虑、进行中或已经将知识图谱融入到RAG中以提高准确性、持久性和确定性,欢迎通过team@whyhow.ai联系我们。或者你可以订阅WhyHow.AI。加入我们在Discord上的讨论,一起探讨规则、确定性以及知识图谱在RAG中的应用。

附录

代码片段

代理定义

  • 查找查询中提到的术语的定义。
    def definitions_search(query_prompt: str, client: Optional[WhyHow]=None) -> Dict[str, str]:  
        """  
        搜索问题提示中的术语定义,并以字典形式返回。  
        """  
        if client is None:  
            client = WhyHow(api_key=WHYHOW_API_KEY, base_url=WHYHOW_API_URL)  

        definitions_response = client.graphs.query_unstructured(  
            graph_id=definitions_graph.graph_id,  
            query=query_prompt,  
        )  

        response_text = definitions_response.answer  
        term_def_pairs = response_text.split('\n')  
        definitions_dict = {}  

        for pair in term_def_pairs:  
            if ':' in pair:  
                term, definition = pair.split(':', 1)  
                definitions_dict[term.strip()] = definition.strip()  

        return definitions_dict  

    query_prompt = """返回此查询中术语的定义:“董事会和CCO如何管理控制职能?”确保术语和定义之间用换行符分隔,且每个条目的首字母大写"""  

    definitions_dict = definitions_search(query_prompt)  

    def print_prompt_definitions_dict(definitions_dict):  
        prompt = "相关定义:\n"  
        for term, definition in definitions_dict.items():  
            prompt += f"{term}: {definition}\n"  
        return prompt  

    print(print_prompt_definitions_dict(定义字典))

路由代理

  • 决定是否继续或停止进程。同时识别包含页脚信息的相关节点或链接到其他节点。这些节点将被递归检索器进一步处理。
    def router_agent(state: AgentState) -> AgentState:  
        # 决定进程是否应该停止或继续  

        starter_prompt_footer = f"""  
            您是一个智能代理,负责从文档中检索图节点的多代理检索过程。这些节点用于回答问题:   
            ```{state['query']}```  

            在此请求下方是一些自动检索的节点列表。   

            您必须确定这些节点列表是否足以回答问题。如果没有足够的信息,您必须识别节点中的任何相关尾注信息。  

            一个节点的尾注可以要求查看文档的其他部分或区域,这将需要一个单独的自然语言搜索。   
            例如:如果尾注说“参见第x段”,应生成一个搜索查询,例如 "Return paragraph x to answer the query '{state['query']}'"。   

            如果没有进一步值得分析的节点,返回一个空响应。仅返回与回答该查询相关的尾注搜索查询。  

            否则,如果任何相关节点需要尾注搜索,请指定 node_id 和搜索查询。  
            节点使用 node_id 标识,并且必须用反引号括起来。       
        """  

        starter_prompt_link = f"""  
            您是一个智能代理,负责从文档中检索图节点的多代理检索过程。这些节点用于回答问题:   
            ```{state['query']}```  

            在此请求下方是一些自动检索的节点列表。   

            您必须确定这些节点列表是否足以回答问题。如果没有足够的信息,您必须识别任何值得探索的链接节点。  

            如果没有进一步值得分析的节点,返回一个空响应。  

            返回一个 node_ids 列表:  
        """  

        # 收集最新的节点和所有的节点  
        last_fetched_nodes_flattened: Dict[str, MultiAgentSearchLocalNode] = {}  
        all_nodes_flattened: Dict[str, MultiAgentSearchLocalNode] = {}

监督代理

  • 监控上下文窗口,如果使用了过多的上下文,则削减节点。
  • 同时也会记录搜索失败,如果在页脚的搜索或链接的节点时找不到节点或相关信息。如果搜索失败次数过多,它会提前终止检索过程。
    def supervisor_agent(state:AgentState) -> AgentState:  

        # 查找搜索失败的情况。这可能是多次搜索某些部分未找到相关信息。
        # 这意味着搜索需要提前终止以避免陷入无限循环。  
        printout = ""  
        for node in state["previous_nodes"]:  
            printout += node.print_node_prompt()  
        for node in state["last_fetched_context_nodes"]:  
            printout += node.print_node_prompt()  

        prompt = f"""  
    你是一个监督代理,负责从文档中检索图节点的多代理检索过程。这些节点是用来回答查询的:  
    ```{state['query']}```  

    以下是自动检索到的节点及其错误列表。如果在检索过程中无法找到进一步的链接或相关节点,返回 END 以结束过程。否则,返回 CONTINUE。   
    只需返回 END 或 CONTINUE 之一。  
    """  

        completion = openai_client.beta.chat.completions.parse(  
            model="gpt-4o-2024-08-06",  
            messages=[  
                {"role": "system", "content": prompt},  
                {"role": "user", "content": printout},  
                {"role": "user", "content": state['search_failures']},  
            ],  
        )

循环代理

  • 获取Router Agent标记的节点信息。如果有新链接,则获取这些新链接;若无新链接,则对文档进行关键字搜索以查找页脚(例如,如果页脚要求参考第7.3节和第7.4节而没有链接,则搜索该文档)。在这一阶段,通过调用LLM来去除冗余节点。
    def recursive_retrieval(state: AgentState) -> AgentState:, 

        current_nodes = state["last_fetched_context_nodes"]  

        for current_node in current_nodes:  
            state["previous_nodes"].append(current_node)  

        new_current_nodes = []  

        # 基于ID查找要获取的节点      

        for node_id in state["node_links_to_fetch"]:  
        # 有时GPT返回的节点ID可能会带有或不带反引号  
            if node_id[0] == "`":  
                node_id = node_id[1:-1]  
            if node_id in local_nodes_map:  
                new_current_nodes.append(local_nodes_map[node_id])  
            else:  
                state["search_failures"].append(f"未能获取ID为{node_id}的节点")  

        for node_id, search_query in state["node_footers_to_fetch"].items():  
            # 通过关键词和BM25搜索获取节点  
            footer_retrieved_nodes = retrieve_with_keywords_bm25(search_query)  
            # LLM会剔除不相关的节点,只保留相关的节点  
            footer_retrieved_nodes, _ = prune_nodes(search_query, footer_retrieved_nodes)  

            for node in footer_retrieved_nodes:  
                new_current_nodes.append(node)  

            # 如果没有获取到节点,就记录失败  
            if len(footer_retrieved_nodes) == 0:  
                state["search_failures"].append(  
                    f"未能获取到查询'{search_query}'的节点"  
                )  

        state["last_fetched_context_nodes"] = new_current_nodes  
        state["pass_count"] += 1  
        state["node_footers_to_fetch"] = {}  
        state["node_links_to_fetch"] = []  

        return state

客服代表

  • 根据检索过程中收集的所有信息和文档中的定义,它给出了查询的答案。
  • 它还会链接到来源,如有段落编号等。
    def answering_agent(state: AgentState) -> AgentState:  
        # 回答代理
        prompt = f"""  
    你是一个回答代理。这些节点是为了回答如下的查询而被自动检索出来的:  
    ```{state['query']}```  

    如果可以,请引用相关的部分或段落,但不要输出带有反引号和井号的完整节点ID。   
    """

通过多图多代理系统检索到的答案的变种

答案 #2:

为了有效地管理控制职能,董事会和首席合规官(CCO)必须合作并建立一个结构化的框架。关键措施包括:

**董事会的职责:**
 - 董事会必须批准CCO的任命、薪酬和解聘,确保他们具有与高级管理层有效沟通的必要地位 **(S 6.3(a),(b))**。
 - 董事会应定期与CCO讨论合规问题,确保CCO能够直接与董事会沟通 **(S 6.3(c),(d))**。
 - 董事会还必须确保CCO获得足够的资源和支持,包括提供必要的人员支持,以履行其职责 **(S 6.3(e)**。

**CCO的角色和独立性:**
 - CCO应监督机构范围内的合规风险管理,并确保职责在合规政策中明确记录和传达 **(S 7.2(a),(b))**。
 - 如果CCO参与其他控制职能,必须确保其独立性和专注于合规职责 **(S 7.3)**。

**与其他职能的协调:**
 - CCO和其它控制职能之间的适当协调至关重要。这包括强有力的信息沟通和寻求合规建议的机制 **(S 7.2(d))**。
 - 董事会必须批准合规责任的分担,以确保不削弱关注点或降低有效性 **(S 7.4(a))**。

**与内部审计分离:**
 - 合规职能应与内部审计保持独立,以保持独立审查的有效性 **(S 7.4(b),S 9.1)**。

**培训和能力建设:**
 - 合规职能负责对其他人员提供培训和指导,以有效管理合规风险 **(S 8.11)**。

通过实施这些步骤,董事会和CCO可以有效地管理控制职能,保持强大的合规和治理框架。

答案三。

董事会和首席合规官(CCO)对控制职能的管理涉及几个关键职责和结构:

**董事会在管理CCO职能中的作用:**
- 董事会必须批准CCO的任命、薪酬和解聘 **(第6.3(a)条)**。
- 董事会应确保CCO有足够的地位,能够与首席执行官和高级管理层有效互动 **(第6.3(b)条)**。
- 董事会与CCO之间应定期沟通,直接讨论合规问题 **(第6.3(c)条)**。
- CCO必须直接、无障碍地接触董事会 **(第6.3(d)条)**。
- 必须为CCO提供足够的资源和支持,以有效地履行职责 **(第6.3(e)条)**。

**共担责任和独立性:**
- 当合规职能被分担时,董事会必须批准这种安排,并且职责应在合规政策中明确界定和记录 **(第7.2条)**。
- CCO不应承担内部审计职责,因为这可能会影响独立审查流程的公正性 **(第7.4条、第9.1条)**。
- CCO必须确保其独立性和专注于合规工作的能力不受额外职责的影响 **(第7.3条)**。

**组织内的责任:**
- 合规是机构内所有管理人员的责任。业务线通过管理控制来管理合规风险,而合规职能则确保这些控制措施足够有效 **(第1.2条)**。
- 内部审计职能提供独立的保证,以确认机构控制的质量和有效性,包括合规方面的控制 **(第1.2(c)条)**。

**控制职能之间的协调:**
- 控制职能和CCO之间的协调安排必须促进对合规风险的一致管理,确保有充分的信息流动和咨询途径 **(第7.2(d)条)**。

通过遵守这些指导方针,董事会和CCO可以有效地管理合规控制职能,确保组织内部合规风险得到适当识别、管理和减轻。
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消