基于LangGraph与LLM的智能体流水线:从政策文本到SHACL知识图谱的自动化构建

📅 2026/8/23 4:37:05
基于LangGraph与LLM的智能体流水线:从政策文本到SHACL知识图谱的自动化构建
1. 项目概述当制度遇上图结构最近在做一个挺有意思的项目客户手里有一大堆内部规章制度文档从信息安全守则到员工行为规范PDF、Word、网页什么格式都有。他们的需求很明确想快速从这些文档里找到特定条款检查新政策是否与旧政策冲突甚至自动化一部分合规审计的流程。这听起来像是典型的NLP信息抽取任务对吧但试过传统的规则匹配和预训练模型微调后我们发现效果总是不尽如人意。政策文本太灵活了同一条款可能有十几种表述方式而且条款之间的逻辑关系比如“必须A除非B”这种结构用传统的“实体-关系”三元组很难清晰表达。就在我们纠结的时候团队里有人提到了知识图谱Knowledge Graph和SHACLShapes Constraint Language。知识图谱能把实体和关系组织成一张网直观地展示“谁约束谁”、“什么情况下适用”。而SHACL是一种W3C标准专门用来描述和验证RDF数据知识图谱的常用数据模型的形状Shape——你可以把它理解为知识图谱的“模式”或“数据字典”。一个想法就冒出来了能不能把这些非结构化的政策文本自动转换成结构化的、用SHACL定义的知识图谱呢这样政策就不再是一堆孤立的文本而是一个可查询、可推理、可验证的数字化规则网络。这就是“PolicyKG”这个项目核心要解决的问题。它不是一个简单的文本解析工具而是一个智能体化的LLM流水线。我们利用大语言模型LLM的理解和生成能力结合LangGraph这样的框架来编排多个智能体Agent协同工作最终目标是将冗长、模糊的自然语言政策精准地翻译成严谨、机器可读的SHACL知识图谱。这对于企业合规、法律科技、智能合约生成等领域有着非常实在的应用价值。2. 核心思路为什么是“智能体流水线”直接让一个LLM“一口吃成胖子”输入整篇政策输出完整的SHACL代码这条路我们试过基本走不通。政策文档的复杂性决定了这是一个需要多步骤、多角度协同的认知过程。这很像现实中一个法务团队的工作流程有人先通读全文划出重点文档解析有人专门识别其中的核心概念和实体实体抽取有人分析这些概念之间的关系和约束条件关系与约束解析最后还有专人负责把这些分析结果整理成标准格式的报告图谱构建与验证。因此PolicyKG的设计核心是**“分而治之”与“协同校验”**。我们采用基于LangGraph的智能体Agent架构将整个翻译流程分解为一系列相对独立、职责明确的子任务每个子任务由一个或多个专门的“智能体”负责。这些智能体在LangGraph编排的“工作流”中有序协作并通过共享的“状态”State传递和迭代中间结果。这样做有几个关键优势模块化与可维护性每个智能体专注于一个特定任务如实体识别、约束逻辑解析其内部的提示词Prompt和逻辑可以独立优化和更新不影响其他模块。比如优化“约束解析智能体”时完全不用改动“实体识别智能体”的代码。降低单次任务复杂度LLM在处理长文本和复杂指令时容易“遗忘”或“混淆”。将任务拆解后每次给LLM的上下文Context更聚焦指令更明确显著提高了输出的准确性和稳定性。实现闭环校验与迭代这是智能体流水线的精髓。我们可以设计一个“验证智能体”检查前序步骤生成的初步图谱是否符合SHACL语法或者与政策原文是否存在明显矛盾。如果发现问题工作流可以自动将问题反馈给相关的前置智能体进行修正形成一个自我改进的循环。这是单次LLM调用无法实现的。整个流水线的输入是原始政策文本输出是符合SHACL标准的知识图谱文件通常是Turtle格式的.ttl文件。中间过程就是多个智能体在LangGraph这个“调度中心”的指挥下接力完成的一次知识提炼与结构化之旅。3. 架构拆解PolicyKG的四大核心智能体基于LangGraph我们将PolicyKG流水线设计为四个核心智能体节点它们通过一个有向图连接共同维护和更新一个全局的“编译状态”。3.1 文档解析与分段智能体这个智能体是流水线的“先锋”。它的任务不是深入理解内容而是为后续处理做好数据准备。输入原始政策文档PDF、DOCX、HTML文本等。核心任务格式统一将不同格式的文档转换为纯文本。这里要注意保留必要的结构信息如标题h1,h2、列表、表格。对于PDF需要使用像pdfplumber或PyMuPDF这类能保留布局信息的库而不是简单提取文字。语义分段这是关键。不能简单地按固定字数或段落切割。我们需要根据政策的逻辑结构进行分段。例如一个典型的政策条款可能包含“条款编号”、“标题”、“主体内容”、“例外情况”、“生效日期”等部分。这个智能体利用LLM如GPT-4或更轻量级的语义分割模型识别这些逻辑边界将文档切割成一个个具有完整语义的“政策片段”Policy Segment。每个片段会附带元数据如所属章节、重要性标签等。输出一个结构化的政策片段列表每个片段是一个包含文本和元数据的字典。实操心得注意直接让LLM切割长文档可能token消耗巨大。一个实用的技巧是采用“滑动窗口”法先按固定大小如1000字做初步粗切然后让LLM判断每个粗切块的边界是否自然并合并或调整相邻块。同时政策文档中的表格是信息富集区务必专门处理将其内容转化为结构化表述如“表1用户数据分类包含以下字段数据类型、存储期限、访问权限...”。3.2 实体与概念抽取智能体这个智能体扮演“术语专家”的角色负责从每个政策片段中提取出核心的“词汇表”。输入上一个智能体输出的政策片段。核心任务识别实体抽取出政策中定义的、或引用的具体事物。这些实体将成为知识图谱中的“节点”。例如在数据安全政策中实体可能包括“个人身份信息PII”、“数据库服务器”、“第三方供应商”、“加密算法AES-256”等。提炼概念/类识别实体的类别或类型这些将成为知识图谱中的“类”。例如“PII”是一个类“张三的身份证号”是这个类的一个实例实体。SHACL中通常用sh:targetClass来指向一个RDF类。定义属性识别描述实体特征或关系的属性。例如“员工”实体可能有属性“所属部门”、“职位级别”。“数据访问”关系可能有属性“访问时间”、“访问目的”。这些属性对应RDF中的谓词。实现方法通常采用Few-shot Prompting。给LLM提供几个标注好的例子让它学习识别政策文本中的实体、类和属性。Prompt要明确指示输出格式例如JSON{ classes: [Employee, SensitiveData], entities: [ {id: emp_001, label: John Doe, type: Employee}, {id: data_001, label: Customer Payment Records, type: SensitiveData} ], properties: [ {id: hasDepartment, label: belongs to department}, {id: requiresEncryption, label: must be encrypted} ] }输出一个结构化的列表包含从所有片段中提取出的类、实体、属性及其之间的初步关联。常见问题实体歧义同一个词在不同语境下可能是实体也可能是类。需要在后续的“约束解析”步骤中结合上下文最终确定其角色。属性重叠不同片段可能用不同词汇描述相同属性如“must be stored in” 和 “shall be kept within”。这个智能体可以初步归一化但更精确的合并可以在图谱构建阶段进行。3.3 约束与逻辑解析智能体这是整个流水线中技术难度最高、也最核心的一环。它的任务是将自然语言描述的规则转化为形式化的逻辑约束。SHACL的强大之处就在于它能表达丰富的约束。输入政策片段以及上一个智能体提取出的相关实体和概念。核心任务解析片段中的约束性语句并映射到SHACL约束组件。这需要深入理解SHACL的词汇表。数据类型约束解析如“必须是字符串”、“日期格式为YYYY-MM-DD”等对应sh:datatype(如xsd:string,xsd:date)。值域约束解析如“部门只能是‘销售部’、‘技术部’或‘市场部’”对应sh:in或枚举类。基数约束解析如“每个员工必须有一个且仅有一个工号”对应sh:minCount,sh:maxCount。逻辑组合解析如“必须满足A且B”对应sh:and“满足A或B即可”对应sh:or“如果不满足A则必须B”对应sh:not和sh:and的组合。属性路径与复杂约束解析如“员工的经理的部门必须与该员工相同”这涉及属性路径sh:path和跨节点的约束。条件约束解析“如果数据被标记为‘敏感’则必须加密存储”。这通常用sh:condition结合sh:shape来表达。实现方法这是一个典型的语义解析任务。我们需要精心设计Prompt将SHACL的语法“教”给LLM。最好的方式是提供详细的、带注释的示例。例如政策原文“所有用户密码长度不得少于8个字符且必须包含大小写字母和数字。”SHACL Shape示例ex:PasswordShape a sh:NodeShape ; sh:targetClass ex:UserAccount ; sh:property [ sh:path ex:password ; sh:minLength 8 ; sh:pattern ^[A-Za-z0-9]$ ; # 注意这个正则只是示例实际需要匹配大小写数字 sh:message Password must be at least 8 characters long and contain both upper and lower case letters and digits. ; ] .我们需要在Prompt中解释sh:minLength、sh:pattern等组件的含义并让LLM学会将自然语言“翻译”成这些组件。输出一组初步的SHACL Shape定义代码片段每个Shape对应一个政策片段或一个核心概念的一组约束。实操心得这是最容易出错的环节。LLM可能会“发明”不存在的SHACL属性或者误解逻辑关系。必须引入“验证”环节。初期可以先生成相对简单的约束如数据类型、枚举值对于复杂逻辑组合可以分步进行先让LLM输出逻辑表达式如“A AND (B OR C)”再由一个确定的、非LLM的转换器将其映射为标准的SHACL结构。3.4 图谱构建与验证智能体这个智能体是“装配工”兼“质检员”。它负责将前几个步骤的产出组装成完整、一致的知识图谱并进行质量检查。输入抽取出的实体/概念/属性列表。解析出的SHACL Shape代码片段。政策片段之间的关联信息如哪个片段引用了哪个概念。核心任务图谱模式构建将提取出的“类”和“属性”组织成RDF SchemaRDFS或OWL本体。定义类之间的层次关系如ex:Employee rdfs:subClassOf ex:Person属性定义域和值域。SHACL Shape整合将分散的Shape定义整合成一个完整的SHACL Shapes图。解决可能存在的冲突例如对同一个属性两个片段给出了不同的数据类型约束。这可能需要更高级的逻辑推理或人工预定义的冲突解决策略如“后出现的覆盖先出现的”或“更具体的约束优先”。实例数据生成可选如果政策文档中包含具体的例子或案例可以尝试生成符合Shape的示例RDF数据用于后续测试。语法与逻辑验证使用SHACL验证器如PySHACL对生成的Shapes图进行语法检查。更重要的是进行“一致性”检查例如检查是否存在矛盾的约束如一个属性既要求sh:minCount 1又要求sh:maxCount 0。输出一个完整的Turtle格式文件包含RDFS/OWL本体定义和SHACL Shapes定义。一份验证报告列出任何语法错误或逻辑警告。LangGraph的状态管理在LangGraph中上述所有智能体的输入输出都读写一个共享的State对象。这个State可能包含以下字段from typing import TypedDict, List, Annotated import operator class PolicyKGState(TypedDict): original_text: str segmented_policies: List[dict] # 存储分段结果 extracted_elements: dict # 存储实体、类、属性 shacl_shapes: List[str] # 存储SHACL代码片段 integrated_knowledge_graph: str # 最终整合的Turtle字符串 validation_errors: List[str] # 存储验证错误每个智能体节点都是一个函数接收这个State修改其中特定的字段然后返回更新后的State。LangGraph负责控制流程的走向例如如果validation_errors不为空则可能将流程跳转回“约束解析智能体”进行修正。4. 基于LangGraph的流水线实现详解LangGraph的核心是定义“图”Graph图中的节点是智能体函数边定义了节点之间的流转条件。下面我们勾勒一个简化的PolicyKG工作流实现。4.1 状态State设计首先定义贯穿整个流程的共享状态。我们使用TypedDict来获得更好的类型提示。from typing import TypedDict, List, Optional from langgraph.graph import StateGraph, END class PolicyKGState(TypedDict): 流水线的全局状态容器。 # 输入 raw_document: str document_format: str # e.g., pdf, docx, html # 阶段一输出 cleaned_text: Optional[str] policy_segments: List[dict] # 每个segment: {id: seg_1, text: ..., metadata: {...}} # 阶段二输出 knowledge_elements: Optional[dict] # {classes: [...], entities: [...], properties: [...]} # 阶段三输出 raw_shacl_shapes: List[str] # 未经处理的SHACL代码块列表 # 阶段四输出 integrated_shacl_graph: Optional[str] # 整合后的完整Turtle字符串 validation_report: Optional[str] # 控制流标志 needs_revision: bool # 验证后是否需要返回修订 revision_feedback: Optional[str] # 给修订环节的反馈信息4.2 节点Node函数定义每个节点对应一个智能体的核心逻辑。这里以“约束与逻辑解析智能体”为例展示其函数结构。from langchain_core.messages import HumanMessage, SystemMessage from langchain_openai import ChatOpenAI import json llm ChatOpenAI(modelgpt-4-turbo-preview) def constraint_parsing_agent(state: PolicyKGState) - PolicyKGState: 约束解析智能体将政策片段转化为SHACL约束。 segments state[policy_segments] elements state[knowledge_elements] # 1. 准备给LLM的上下文和指令 system_prompt 你是一个精通SHACLShapes Constraint Language和自然语言处理的专家。 你的任务是将用自然语言描述的政策规则精确地转换为SHACL Shapes代码。 请只输出有效的Turtle格式SHACL代码块不要有任何额外解释。 parsed_shapes [] for segment in segments: # 2. 构建针对单个片段的Prompt human_prompt f 请将以下政策片段转换为SHACL Shape。请使用以下已识别的知识元素作为参考 类: {elements.get(classes, [])} 属性: {elements.get(properties, [])} 政策片段文本 {segment[text]} 请生成对应的SHACL NodeShape或PropertyShape。确保使用正确的SHACL属性如sh:datatype, sh:minCount, sh:in, sh:pattern等。 如果规则涉及条件逻辑如 if...then请使用sh:condition。 将生成的Shape的URI前缀定义为 ex:。 # 3. 调用LLM messages [ SystemMessage(contentsystem_prompt), HumanMessage(contenthuman_prompt) ] response llm.invoke(messages) # 4. 解析并存储结果 raw_shape_code response.content.strip() # 简单的清洗确保代码块被正确提取 if turtle in raw_shape_code: raw_shape_code raw_shape_code.split(turtle)[1].split()[0].strip() elif in raw_shape_code: raw_shape_code raw_shape_code.split()[1].split()[0].strip() parsed_shapes.append(raw_shape_code) print(f[约束解析] 已处理片段 {segment[id]}) # 5. 更新状态 new_state state.copy() new_state[raw_shacl_shapes] parsed_shapes return new_state其他智能体节点document_segmentation_agent,entity_extraction_agent,integration_validation_agent也遵循类似模式只是内部Prompt和逻辑处理不同。4.3 边Edge与流程控制定义节点之间的流转逻辑特别是条件跳转以实现验证-修订循环。from langgraph.graph import StateGraph, END # 创建图构建器 workflow StateGraph(PolicyKGState) # 添加节点 workflow.add_node(document_segmenter, document_segmentation_agent) workflow.add_node(entity_extractor, entity_extraction_agent) workflow.add_node(constraint_parser, constraint_parsing_agent) workflow.add_node(integrator_validator, integration_validation_agent) # 设置入口点 workflow.set_entry_point(document_segmenter) # 添加普通顺序边 workflow.add_edge(document_segmenter, entity_extractor) workflow.add_edge(entity_extractor, constraint_parser) workflow.add_edge(constraint_parser, integrator_validator) # 添加条件边根据验证结果决定下一步 def decide_after_validation(state: PolicyKGState) - str: 决策函数检查验证结果决定是结束还是返回修订。 if state.get(needs_revision, False): # 如果需要修订可以指定回到哪个节点。这里假设回到约束解析器。 # 更复杂的逻辑可以携带revision_feedback到特定节点。 return constraint_parser else: return END workflow.add_conditional_edges( integrator_validator, # 源节点 decide_after_validation, # 决策函数 { constraint_parser: constraint_parser, # 如果返回constraint_parser则跳转到该节点 END: END # 如果返回END则结束流程 } ) # 编译图 app workflow.compile()4.4 执行与迭代现在我们可以运行这个工作流。LangGraph会自动管理状态的传递和节点的执行顺序。# 初始化状态 initial_state: PolicyKGState { raw_document: 你的政策文本内容..., document_format: text, policy_segments: [], knowledge_elements: None, raw_shacl_shapes: [], integrated_shacl_graph: None, validation_report: None, needs_revision: False, revision_feedback: None } # 执行工作流 final_state app.invoke(initial_state) # 查看最终结果 print(最终生成的SHACL图谱) print(final_state.get(integrated_shacl_graph, No graph generated.)) print(\n验证报告) print(final_state.get(validation_report, No validation performed.))如果validation_report指出错误并且needs_revision被设置为True工作流会根据decide_after_validation函数的逻辑自动跳转回constraint_parser节点。此时我们可以修改constraint_parsing_agent函数使其能读取state[revision_feedback]来获得更具体的修改指导从而实现智能化的迭代修正。5. 关键挑战与实战调优经验将非结构化政策转换为形式化的SHACL即使在智能体流水线的加持下也绝非易事。以下是我们在实践中遇到的主要挑战及应对策略。5.1 政策语言的模糊性与歧义挑战政策中大量使用“通常”、“必要时”、“在合理范围内”等模糊词汇。LLM可能将其过度具体化或错误解读。应对策略Prompt工程在给LLM的指令中明确说明如何处理模糊性。例如“如果遇到‘合理时间’请将其标注为需要人工审查的模糊约束并建议一个可能的默认值如‘24小时’但使用sh:annotation注明此建议来源。”置信度评分让LLM在输出每个约束时附带一个置信度分数。低置信度的输出会被标记进入人工审核队列或触发更保守的转换规则。分层处理区分“硬性约束”必须、禁止和“指导性原则”应该、建议。前者转换为严格的SHACL约束如sh:minCount 1后者可能转换为sh:info注解或更宽松的约束。5.2 SHACL表达的复杂性挑战复杂的嵌套逻辑如多重条件、例外条款很难直接、准确地映射到SHACL的sh:and、sh:or、sh:not、sh:condition组合上。LLM可能生成语法正确但语义错误的复杂Shape。应对策略分步翻译不要试图一步到位。先让一个智能体将自然语言规则翻译成中间表示形式比如一个结构化的逻辑表达式树或简单的自定义DSL。然后用另一个确定性的、非LLM的转换器将这个中间表示转换成标准的SHACL。这大大降低了LLM的出错的破坏范围。模板库为常见的政策约束模式建立SHACL模板库。例如“所有A必须具有属性P且P的值来自集合S”对应一个模板。LLM的任务简化为识别政策文本符合哪个模板并填充模板参数A, P, S。后置简化与验证使用SHACL推理工具或简单的图模式匹配对生成的复杂Shape进行等价性简化并验证其逻辑一致性。5.3 知识图谱的一致性维护挑战从同一份政策的不同部分甚至多份相关政策中提取的知识可能存在冲突或重复。例如政策A定义“员工”有属性“工号”政策B定义“雇员”有属性“员工编号”这可能是同一回事。应对策略实体链接与消歧在“实体抽取”环节后增加一个专门的“消歧与对齐”智能体。它利用预训练的实体嵌入或字符串相似度算法将指代相同事物的不同表述链接到唯一的URI上。冲突检测与解决策略在“图谱构建”智能体中实现一套规则化的冲突解决策略。例如“后法优于先法”按文档时间戳、“具体规定优于一般规定”通过分析约束的严格程度判断、“人工裁决”将无法自动解决的冲突上报。这些策略可以编码在LangGraph的状态判断逻辑中。版本控制为生成的SHACL图谱引入版本概念。当政策更新时可以对比新旧图谱清晰地展示哪些约束被增加、删除或修改。5.4 流水线的性能与成本挑战处理长篇政策文档需要调用多次LLMtoken消耗大速度慢成本高。应对策略智能分段与缓存优化“文档解析智能体”确保分段尽可能合理减少不必要的片段数量。对相同的或高度相似的策略条款如不同部门但内容相似的保密条款可以尝试识别并复用已解析的结果。模型分级调用不是所有任务都需要最强的GPT-4。实体识别等相对简单的任务可以使用更便宜、更快的模型如GPT-3.5-Turbo、Claude Haiku或开源模型。只在最复杂的逻辑解析环节使用大模型。异步与并行LangGraph支持异步节点执行。如果政策片段之间独立性较高“约束解析”可以对多个片段并行处理显著提升整体速度。迭代式精炼不要追求一次完美。第一遍流水线可以快速生成一个“草稿版”图谱包含高置信度的简单约束。第二遍再针对模糊、复杂或低置信度的部分投入更多计算资源如使用思维链CoT或更详细的Prompt进行精炼。6. 效果评估与未来展望评估PolicyKG的效果不能只看生成的SHACL代码的语法正确性更要看其“语义保真度”——即生成的图谱是否准确、完整地反映了原始政策的精神和细节。评估维度准确性随机抽样政策条款由领域专家判断自动生成的SHACL约束是否与人工解读一致。可以计算准确率、召回率。完整性检查重要政策概念和约束是否都被覆盖。可以对比人工标注的政策要素清单与系统提取的清单。可用性将生成的SHACL图谱加载到图数据库如Neo4j、Amazon Neptune或验证引擎中用测试数据验证其是否能正确“放行”合规数据和“拦截”违规数据。效率提升对比完全人工编写SHACL与使用PolicyKG辅助包括人工修正时间所需的总时长。未来可能的演进方向多模态输入支持处理包含流程图、表格的政策文档结合VLM视觉语言模型解析图表中的逻辑。动态策略与实时合规与业务系统集成使知识图谱不仅能描述静态政策还能对实时产生的数据如交易记录、系统日志进行流式合规检查。解释性增强为每个自动生成的SHACL约束附加“溯源”信息链接回政策原文的具体段落当约束被触发时能向用户解释“这个要求是根据政策第X章第Y条制定的”。联邦式策略管理处理来自不同来源如母公司、子公司、合作伙伴的策略并管理它们之间的继承、覆盖和冲突关系构建一个层次化的、联邦式的策略知识图谱。PolicyKG这类项目本质上是利用LLM的认知能力来弥合人类自然语言与机器可执行逻辑之间的“语义鸿沟”。它不是一个全自动的“黑箱”而是一个强大的“人机协同”工具。它的价值在于将法务、合规专家从繁琐、易错的代码编写工作中解放出来让他们能更专注于高层的策略制定和复杂的案例裁决而将结构化的、重复性的规则表述工作交给智能体流水线去完成。在强监管和数字化并行的时代这种能力正变得越来越不可或缺。