LangGraph系列:多智能体终极落地,智能合同审核系统全流程实战

B站影视 韩国电影 2025-11-13 13:01 1

摘要:在商业合作中,合同审核是守护企业风险的关键环节,但传统人工审核模式往往面临效率低下、风险遗漏、个性化需求难满足等痛点。随着大模型技术的成熟,多Agent协作系统逐渐成为解决复杂任务的主流方案,通过将专业化的AI Agent组合起来,分工协作完成条款抽取、风险评

在商业合作中,合同审核是守护企业风险的关键环节,但传统人工审核模式往往面临效率低下、风险遗漏、个性化需求难满足等痛点。随着大模型技术的成熟,多Agent协作系统逐渐成为解决复杂任务的主流方案,通过将专业化的AI Agent组合起来,分工协作完成条款抽取、风险评估、合规检查等工作,既能提升审核效率,又能降低人为失误,本文将以工业级智能合同审核系统为例,详细讲解如何利用LangGraph构建功能完备的多Agent系统,涵盖架构设计、状态管理、工具开发、记忆机制和人机协作等核心技术,所有代码均可直接落地使用。

合同审核不是单一任务,而是包含条款提取、风险识别、合规校验、个性化建议等多个环节的复杂流程。单一Agent很难同时具备法律专业知识、精准信息抽取能力和个性化适配能力,而多Agent架构通过"专业化分工+协同协作"的模式,能完美解决这一问题。

具体来说,合同审核场景对多Agent系统有三大核心诉求:一是精准性,必须准确抽取赔偿责任、终止条款等关键信息,不能出现遗漏或误判;二是个性化,不同企业的风险容忍度不同,比如保守型企业对赔偿上限敏感,而激进型企业更关注终止条款的灵活性;三是安全性,高风险条款必须有人工介入环节,避免AI自主决策带来的法律风险。

LangGraph作为LangChain生态中专门用于构建状态ful多Agent系统的框架,其核心优势在于强大的状态管理和灵活的流程编排能力,通过图结构定义Agent之间的协作关系,用共享状态传递上下文,配合检查点机制实现流程中断与恢复,恰好满足合同审核场景的复杂需求。我们选择Supervisor(主管)架构作为核心,由一个中心Agent负责任务路由和协调,将复杂任务分派给专业化的子Agent,形成"主管统筹+专家执行"的协作模式。

在多Agent系统中,状态(State)是贯穿整个流程的"共享笔记本",所有Agent的工作成果、上下文信息、用户偏好都通过状态传递。一个合理的状态设计直接决定了系统的灵活性和可扩展性,我们基于TypedDict定义合同审核系统的共享状态,同时兼顾短期记忆和长期记忆的需求。

首先来看状态定义的完整代码,其中每个字段都对应实际业务场景的核心需求:

from typing_extensions import TypedDictfrom typing import Annotated, Listfrom langgraph.graph.message import AnyMessage, add_messagesfrom langgraph.managed.is_last_step import RemainingSteps# LangGraph 状态定义class ContractState(TypedDict):"""合同审核 Agent 的共享状态,定义了流经图节点的所有数据结构"""# 客户/项目标识符,用于长期记忆检索(比如区分不同企业的审核需求)project_id: str# 核心合同文本,从用户上传的文件或输入中提取contract_text: str# 完整的会话历史,用于短期记忆和上下文维护(自动累加)messages: Annotated[List[AnyMessage], add_messages]# 从长期记忆中加载的用户风险偏好(比如"保守型,关注赔偿条款和违约责任")loaded_memory: str# 当前合同分析的风险报告摘要,最终会呈现给用户risk_report: str# 循环计数器,防止Agent无限递归调用工具remaining_steps: RemainingSteps

这个状态设计有两个关键细节需要重点理解,这也是LangGraph实现记忆能力的核心:

第一个是messages字段的add_messages注解,它能让每次Agent或工具的输出自动追加到会话历史中,无需手动管理。比如条款抽取Agent提取完赔偿条款后,其输出会自动存入messages,后续风险评估Agent可以直接从历史消息中获取该条款信息,无需重复抽取,这就是系统的"短期记忆",确保协作过程的连贯性。

第二个是loaded_memory字段,它用于存储跨会话的持久化信息,也就是"长期记忆"。比如某企业之前设置过"风险容忍度:保守,重点关注赔偿上限不超过合同金额30%",这些偏好会被存储在长期记忆中,下次该企业上传新合同审核时,系统会自动加载这些信息,让风险评估更贴合企业需求。

这里需要注意remaining_steps字段的作用,多Agent系统中很容易出现Agent之间循环调用的问题,比如抽取Agent调用工具后,风险Agent又要求重新抽取,通过设置剩余步骤计数器,当步骤数耗尽时系统会自动触发人工介入,避免无限循环。

多Agent系统的核心价值在于"专业的人做专业的事",我们将合同审核流程拆分为两个核心子Agent:合同条款抽取Agent和法律风险评估Agent,每个Agent都配备专属工具,确保任务执行的精准性。工具是Agent与外部世界交互的桥梁,通过@tool装饰器可以快速定义可被Agent调用的函数,支持参数校验和自动文档生成。

条款抽取是合同审核的基础,只有准确提取出赔偿责任、终止条款、违约责任等核心内容,后续的风险评估才能顺利开展。这个Agent的核心职责是"找得准、摘得精",我们为其设计extract_clause_summary工具,专门用于抽取指定条款并生成摘要。

from langchain_core.tools import toolimport json@tooldef extract_clause_summary(contract_text: str, clause_name: str) -> str:"""从合同文本中抽取指定条款的摘要,支持常见商业合同条款类型Args:contract_text (str): 待审核的完整合同文本clause_name (str): 想要抽取的条款名称(例如: '终止条款' 或 '赔偿责任')Returns:str: 抽取到的条款原文及其精炼摘要,格式为"原文片段:xxx;摘要:xxx""""# 实际生产环境中,此处会对接RAG系统或专门的条款抽取模型(如LegalBERT)# 以下为模拟实现,真实场景需替换为模型调用逻辑clause_map = {"赔偿责任": {"原文片段": "双方确认,任何一方违反本合同约定导致对方损失的,赔偿责任上限为合同总金额的50%","摘要": "赔偿责任上限为合同总金额的50%"},"终止条款": {"原文片段": "本合同有效期内,任意一方如需终止合同,应提前30天向对方发出书面通知,通知生效后合同终止","摘要": "任意一方提前30天书面通知即可终止合同"},"违约责任": {"原文片段": "违约方应在收到守约方书面通知后15日内承担违约责任,逾期未承担的,按日加收合同金额0.1%的违约金","摘要": "违约方需在15日内承担责任,逾期按日加收0.1%违约金"}}if clause_name in clause_map:item = clause_map[clause_name]return f"原文片段:{item['原文片段']};摘要:{item['摘要']}"else:return f"未在合同中找到'{clause_name}'相关条款,请检查条款名称是否准确"# 将工具绑定到Agent(后续会与LLM结合)extraction_tools = [extract_clause_summary]

这个工具的设计有两个关键点:一是参数明确,contract_text接收完整合同文本,clause_name指定要抽取的条款,符合Agent的调用习惯;二是返回格式标准化,同时提供原文片段和摘要,既保证审核的可追溯性,又方便后续风险评估Agent快速获取核心信息。实际应用中,我们可以基于RAG系统优化工具性能,将合同文本分割为 chunks 存入向量数据库,工具调用时通过语义检索快速定位目标条款,比纯LLM抽取准确率更高。

风险评估Agent是系统的"决策核心",其职责是根据抽取到的条款、用户风险偏好和外部法律法规,给出风险等级和整改建议。我们为其设计check_regulatory_compliance工具,专门用于校验条款的合规性,同时结合用户偏好判断风险等级。

@tooldef check_regulatory_compliance(clause_summary: str, user_risk_preference: str = "平衡") -> str:"""对照国家法律法规和用户风险偏好,评估条款的潜在风险Args:clause_summary (str): 待检查的条款摘要(来自抽取Agent的输出)user_risk_preference (str): 用户风险偏好(激进/平衡/保守),默认值为"平衡"Returns:str: 包含合规性结果、风险等级和建议的评估报告"""# 实际生产环境中,此处会对接外部法律法规数据库(如国家法律法规数据库API)# 以下为模拟实现,真实场景需替换为API调用或数据库查询逻辑risk_level = "低"compliance_result = "符合当前法律法规要求"suggestion = "无需修改"# 合规性检查:模拟金融行业特殊要求if "赔偿责任" in clause_summary and "50%" in clause_summary:compliance_result = "符合当前法律法规要求,但需注意金融行业特殊规定"# 结合用户偏好判断风险等级if user_risk_preference == "保守":risk_level = "中"suggestion = "建议将赔偿责任上限调整为合同总金额的30%,更符合保守型风险偏好,同时降低金融行业监管风险"elif user_risk_preference == "激进":risk_level = "低"suggestion = "当前条款符合激进型风险偏好,但需在合同补充说明中明确赔偿范围"# 合规性检查:模拟终止条款的合理性elif "终止条款" in clause_summary and "30天" in clause_summary:if user_risk_preference == "保守":risk_level = "低"suggestion = "30天通知期符合保守型偏好,可保留条款"elif user_risk_preference == "激进":risk_level = "中"suggestion = "建议将通知期缩短至15天,更符合激进型企业的灵活经营需求"return (f"合规性检查结果:{compliance_result}\n"f"风险等级:{risk_level}\n"f"整改建议:{suggestion}")# 将工具绑定到Agentrisk_tools = [check_regulatory_compliance]

这个工具的核心价值在于"个性化风险评估",它不仅校验条款是否符合法律法规,还会结合用户的风险偏好调整评估结果。比如同样是"赔偿上限50%"的条款,保守型用户会被判定为中风险,而激进型用户则为低风险,这正是多Agent系统比单一工具更智能的地方。

每个Agent都需要与LLM结合才能发挥作用,我们通过提示词定义Agent的角色和行为准则,确保Agent能正确调用工具、处理结果。以下是三个核心Agent的提示词设计,基于ChatPromptTemplate实现:

from langchain_openai import ChatOpenAIfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_core.messages import SystemMessage# 初始化LLM(支持GPT-4o、通义千问、文心一言等兼容模型)llm = ChatOpenAI(model="gpt-4o", temperature=0.1) # 低温度确保输出稳定# 1. 条款抽取Agent的提示词extraction_prompt = ChatPromptTemplate.from_messages([SystemMessage("你是专业的合同条款抽取专家,精通各类商业合同的结构和关键条款。""你的核心任务:根据用户需求或主管Agent的指令,使用提供的extract_clause_summary工具,从合同文本中精准抽取指定条款。""工作规则:""1. 必须先确认需要抽取的条款名称,若未明确则询问用户或主管;""2. 抽取时必须使用提供的工具,不得仅凭记忆或猜测;""3. 工具返回结果后,整理成'条款名称+原文片段+摘要'的格式,无需额外添加无关信息;""4. 若工具返回'未找到相关条款',直接如实反馈,无需编造。"),("placeholder", "{messages}"), # 接收历史消息和上下文])# 2. 风险评估Agent的提示词risk_prompt = ChatPromptTemplate.from_messages([SystemMessage("你是严谨的法律风险评估师,具备丰富的商业合同审核经验和合规知识。""你的核心任务:根据抽取Agent提供的条款摘要、用户的风险偏好(来自loaded_memory),使用check_regulatory_compliance工具评估风险。""工作规则:""1. 必须先获取完整的条款摘要和用户风险偏好,缺一不可;""2. 必须使用提供的工具进行合规性检查,不得自行判断法律法规要求;""3. 评估结果需包含合规性、风险等级(低/中/高)、整改建议三部分,逻辑清晰;""4. 若条款存在高风险(如赔偿上限超过50%且用户为保守型),需明确标注并建议人工介入。"),("placeholder", "{messages}"),])# 3. 主管Agent的提示词(核心路由角色)supervisor_prompt = ChatPromptTemplate.from_messages([SystemMessage("你是高级多Agent系统主管,负责统筹合同审核的全流程,合理分配任务并确保流程顺畅。""你的核心任务:根据用户最新请求和当前状态,决定下一步行动,路由到正确的子Agent。""可用子Agent:合同条款抽取Agent(extraction_agent)、法律风险评估Agent(risk_agent)。""工作规则:""1. 先判断当前状态:若未加载用户记忆,等待记忆加载完成;若未抽取条款,先调用extraction_agent;""2. 抽取完成后,调用risk_agent进行风险评估;""3. 风险评估结果若为高风险,触发人工介入(返回'人工介入');""4. 所有任务完成后,返回'FINISH',触发长期记忆更新;""5. 不得直接处理具体任务(如抽取条款、评估风险),仅负责路由和决策。"),("placeholder", "{messages}"),])

提示词设计的关键在于"明确角色、划定边界、给出规则",每个Agent都知道自己的身份(抽取专家/评估师/主管),知道能做什么(使用指定工具)、不能做什么(主管不直接处理具体任务),这样才能避免Agent行为混乱,确保协作顺畅。

多Agent系统要具备"智能",必须拥有记忆能力,短期记忆用于维护当前会话的上下文,长期记忆用于存储跨会话的用户偏好。LangGraph通过Checkpointer实现短期记忆的持久化和恢复,通过Store实现长期记忆的存储和加载,两者结合让系统既能"记住当前事",又能"记住老规矩"。

短期记忆由LangGraph的Checkpointer负责管理,它能记录每次流程运行的完整状态,支持暂停和恢复。比如用户上传合同后,系统正在抽取条款时突然中断,下次启动时可以通过检查点恢复之前的状态,无需重新上传合同。

from langgraph.checkpoint.memory import MemorySaver# 短期记忆:记录和恢复每一次LangGraph运行的完整状态checkpointer = MemorySaver

这个Checkpointer会被传递给每个Agent和图的编译过程,自动记录状态的变化。在实际应用中,我们可以将MemorySaver替换为更持久化的存储(如RedisCheckpoint),支持分布式部署场景下的状态共享。

4.2 长期记忆:基于InMemoryStore的用户偏好管理

长期记忆用于存储跨会话的持久化信息,比如用户的风险偏好、关注的条款类型、历史审核记录等。我们使用InMemoryStore模拟长期存储,实际生产环境中可以替换为PostgreSQL、MongoDB等数据库。

首先定义用户偏好的结构化模型,确保存储的数据规范:

from langgraph.store.memory import InMemoryStorefrom pydantic import BaseModel, Field# 结构化用户偏好模型,确保数据格式统一class UserProfile(BaseModel):risk_tolerance: str = Field(description="用户风险容忍度:激进、平衡或保守")preferred_clauses: List[str] = Field(description="用户最关注的关键条款列表,如['赔偿责任', '终止条款']")industry: str = Field(description="用户所属行业,用于适配行业特定法规,如'金融'、'互联网'")# 初始化长期存储long_term_store = InMemoryStore

然后实现两个核心节点:load_memory(加载用户偏好)和create_memory(更新用户偏好),这两个节点会作为流程的一部分,自动执行记忆的加载和更新。

def load_memory(state: ContractState) -> ContractState:"""从长期存储加载用户偏好,存入loaded_memory字段"""# 从状态中获取项目ID(每个用户/企业对应唯一project_id)project_id = state.get("project_id", "default_project")# 从长期存储中获取用户档案stored_data = long_term_store.get(project_id)if stored_data and "user_profile" in stored_data:user_profile = stored_data["user_profile"]# 将结构化的用户偏好转换为自然语言,方便Agent理解loaded_memory = (f"用户风险容忍度:{user_profile.risk_tolerance},"f"关注条款:{', '.join(user_profile.preferred_clauses)},"f"所属行业:{user_profile.industry}")return {"loaded_memory": loaded_memory}else:# 若未找到历史偏好,使用默认值return {"loaded_memory": "用户风险容忍度:平衡,关注条款:['赔偿责任', '终止条款', '违约责任'],所属行业:通用"}def create_memory(state: ContractState) -> ContractState:"""根据本次会话结果更新长期存储中的用户偏好"""project_id = state.get("project_id", "default_project")loaded_memory = state.get("loaded_memory", "")messages = state.get("messages", )# 从会话历史中提取用户最新的风险偏好(实际场景中会用LLM解析messages)# 这里模拟提取逻辑:若用户在人工介入时明确修改了风险偏好,则更新new_risk_tolerance = "平衡"new_preferred_clauses = ["赔偿责任", "终止条款", "违约责任"]new_industry = "通用"# 解析人工介入消息中的偏好更新(示例)for msg in messages:if hasattr(msg, "content") and "风险偏好" in msg.content:if "保守" in msg.content:new_risk_tolerance = "保守"elif "激进" in msg.content:new_risk_tolerance = "激进"# 提取用户关注的新条款if "关注" in msg.content:import reclauses = re.findall(r"['\"](.*?)['\"]", msg.content)if clauses:new_preferred_clauses = clauses# 更新长期存储updated_profile = UserProfile(risk_tolerance=new_risk_tolerance,preferred_clauses=new_preferred_clauses,industry=new_industry)long_term_store.put(project_id, {"user_profile": updated_profile})print(f"[长期记忆更新] 项目 {project_id}:风险容忍度={new_risk_tolerance},关注条款={new_preferred_clauses}")return {} # 仅执行副作用,不修改状态其他字段

这两个节点的工作流程很清晰,load_memory在流程开始时执行,自动加载用户的历史偏好;create_memory在流程结束时执行,根据本次会话的交互(比如用户人工介入时修改了偏好)更新长期存储。这样一来,系统会越用越智能,每次审核都会更贴合用户的实际需求。

合同审核是高风险场景,AI的决策不能完全替代人工,对于高风险条款(如赔偿上限过高、终止条款不合理),必须让人类审核员介入确认,这就是人机协作(Human-in-the-Loop, HITL)。我们设计专门的human_in_the_loop_node节点,当主管Agent判断需要人工介入时,流程会暂停并等待人工输入,确认后再继续执行。

from langchain_core.messages import HumanMessage, AIMessagedef human_in_the_loop_node(state: ContractState) -> ContractState:"""高风险场景下的人工介入节点,暂停流程等待人工审核"""# 获取主管Agent的最新消息,判断是否需要人工介入last_message = state["messages"][-1]contract_text = state["contract_text"]loaded_memory = state["loaded_memory"]# 仅当主管Agent未返回FINISH且包含高风险提示时,触发人工介入if "FINISH" not in last_message.content and ("高风险" in last_message.content or "人工介入" in last_message.content):print("\n" + "="*50)print("⚠️ 高风险警报:需要人工介入审核")print("="*50)print(f"项目ID:{state.get('project_id')}")print(f"用户偏好:{loaded_memory}")print(f"Agent当前判断:{last_message.content}")print(f"合同核心内容:{contract_text[:500]}..." if len(contract_text) > 500 else f"合同核心内容:{contract_text}")print("\n请人工审核后输入指令(例如:'风险确认,同意AI建议'或'修改风险偏好为保守,重新评估'):")# 实际应用中,这里会对接UI界面,支持审核员输入和文件上传# 此处用input模拟人工输入(阻塞等待)human_input = input("> ")print("="*50 + "\n")# 将人工输入作为HumanMessage添加到状态中,供主管Agent重新处理return {"messages": [HumanMessage(content=f"人工审核指令:{human_input}")]}# 若无需人工介入,直接返回状态return state

这个节点的设计有三个关键细节:一是触发条件明确,只有高风险场景才会暂停,避免过度打扰人工;二是提供完整的上下文,让审核员能快速了解情况(包括项目ID、用户偏好、Agent判断、合同核心内容);三是支持灵活的人工指令,审核员可以确认风险、修改偏好或要求重新评估,系统会根据指令调整后续流程。

在实际应用中,我们可以将这个节点与企业的OA系统或审核平台对接,审核员会收到通知消息,在平台上完成审核后,指令会自动传递给Agent系统,实现异步协作,这也是LangGraph状态管理的优势,支持流程的中断和恢复。

所有节点和Agent定义完成后,接下来就是通过LangGraph的StateGraph构建完整的协作流程。我们需要定义节点之间的连接关系、条件路由规则,让整个系统按照"加载记忆→主管决策→子Agent执行→人工介入(可选)→更新记忆→结束"的逻辑运行。

首先创建子Agent和工具执行节点,利用LangGraph的预置函数简化开发:

from langgraph.prebuilt import ToolExecutor, ToolNode, create_react_agent, create_supervisorfrom langgraph.graph import StateGraph, END, START# 工具执行器:负责执行Agent调用的工具extraction_executor = ToolExecutor(extraction_tools)risk_executor = ToolExecutor(risk_tools)# 创建ReAct模式的子Agent(LLM + 工具 + 提示词)def create_sub_agent(llm, tools, prompt):"""封装子Agent的创建逻辑,返回Agent和工具执行节点"""agent_runnable = create_react_agent(llm=llm.bind_tools(tools), # 将工具绑定到LLM,让LLM知道可以调用哪些工具tools=tools,checkpointer=checkpointer, # 绑定检查点,支持状态恢复prompt=prompt)tool_node = ToolNode(executor=ToolExecutor(tools))return agent_runnable, tool_node# 创建条款抽取Agent和工具节点extraction_agent, extraction_tool_node = create_sub_agent(llm, extraction_tools, extraction_prompt)# 创建风险评估Agent和工具节点risk_agent, risk_tool_node = create_sub_agent(llm, risk_tools, risk_prompt)# 创建主管Agent(负责路由决策)supervisor_agent = create_supervisor(llm=llm,agents=["extraction_agent", "risk_agent"], # 告知主管可用的子Agentsystem_prompt=supervisor_prompt,handle_messages_correctly=True # 确保消息格式兼容)

这里的create_react_agent是LangGraph的预置函数,能快速创建支持工具调用的ReAct模式Agent,ReAct模式是Agent调用工具的经典范式,通过"思考→行动→观察→思考"的循环,确保工具调用的准确性。

流程的灵活性取决于路由规则,我们定义两个核心路由函数:check_for_tool_call判断Agent是否需要调用工具,route_supervisor判断主管Agent的下一步行动。

def check_for_tool_call(state: ContractState) -> str:"""检查Agent的最新消息是否包含工具调用,决定是否执行工具"""last_message = state["messages"][-1]# 若消息包含工具调用,路由到工具执行节点;否则返回主管return "continue" if last_message.tool_calls else "end"def route_supervisor(state: ContractState) -> str:"""主管Agent的路由逻辑,决定下一步执行哪个节点"""last_message = state["messages"][-1]content = last_message.content# 路由到条款抽取Agentif "extraction_agent" in content:return "extraction_agent"# 路由到风险评估Agentelif "risk_agent" in content:return "risk_agent"# 触发人工介入elif "高风险" in content or "人工介入" in content:return "human_in_the_loop"# 任务完成,更新长期记忆后结束elif "FINISH" in content:return "create_memory"# 默认路由:返回主管重新决策else:return "supervisor"

这两个路由函数是流程的"交通指挥灯",check_for_tool_call确保Agent只有在需要调用工具时才执行工具,避免无效操作;route_supervisor让主管Agent能根据实际情况灵活分配任务,比如先抽取条款再评估风险,遇到高风险就触发人工介入。

最后,我们通过StateGraph将所有节点和路由规则组装起来,形成完整的多Agent系统:

# 初始化状态图builder = StateGraph(ContractState)# 1. 添加核心业务节点builder.add_node("load_memory", load_memory) # 加载长期记忆builder.add_node("create_memory", create_memory) # 更新长期记忆builder.add_node("human_in_the_loop", human_in_the_loop_node) # 人工介入builder.add_node("supervisor", supervisor_agent) # 主管Agent# 2. 添加子Agent和工具节点builder.add_node("extraction_agent", extraction_agent) # 条款抽取Agentbuilder.add_node("extraction_tool_node", extraction_tool_node) # 抽取工具执行builder.add_node("risk_agent", risk_agent) # 风险评估Agentbuilder.add_node("risk_tool_node", risk_tool_node) # 风险工具执行# 3. 定义节点之间的连接关系# 流程起点:加载记忆builder.set_entry_point("load_memory")# 记忆加载完成后,交给主管Agent决策builder.add_edge("load_memory", "supervisor")# 主管Agent的条件路由:根据决策结果跳转builder.add_conditional_edges("supervisor",route_supervisor,{"extraction_agent": "extraction_agent","risk_agent": "risk_agent","human_in_the_loop": "human_in_the_loop","create_memory": "create_memory"})# 条款抽取Agent的循环:调用工具→返回Agent→返回主管builder.add_conditional_edges("extraction_agent",check_for_tool_call,{"continue": "extraction_tool_node", # 需要调用工具,执行工具"end": "supervisor" # 不需要工具,返回主管})builder.add_edge("extraction_tool_node", "extraction_agent") # 工具执行完成,返回Agent处理结果# 风险评估Agent的循环:调用工具→返回Agent→返回主管builder.add_conditional_edges("risk_agent",check_for_tool_call,{"continue": "risk_tool_node","end": "supervisor"})builder.add_edge("risk_tool_node", "risk_agent")# 人工介入完成后,返回主管重新决策builder.add_edge("human_in_the_loop", "supervisor")# 更新长期记忆后,流程结束builder.add_edge("create_memory", END)# 编译图:启用检查点机制,支持状态恢复contract_review_app = builder.compile(checkpointer=checkpointer)

图编译完成后,我们可以通过调用contract_review_app.invoke启动系统,传入初始状态参数即可。以下是一个完整的测试示例:

# 测试用例:用户上传一份合同,请求审核initial_state = {"project_id": "company_a_2024", # A公司的项目ID"contract_text": """商业合作合同甲方:A公司乙方:B公司1. 赔偿责任:双方确认,任何一方违反本合同约定导致对方损失的,赔偿责任上限为合同总金额的50%。2. 终止条款:本合同有效期内,任意一方如需终止合同,应提前30天向对方发出书面通知,通知生效后合同终止。3. 违约责任:违约方应在收到守约方书面通知后15日内承担违约责任,逾期未承担的,按日加收合同金额0.1%的违约金。""","messages": , # 初始会话历史为空"loaded_memory": "", # 初始无加载的记忆"risk_report": "", # 初始无风险报告"remaining_steps": 10 # 最多允许10步流程}# 运行多Agent系统result = contract_review_app.invoke(initial_state)# 输出最终结果print("\n" + "="*60)print(" 智能合同审核报告")print("="*60)print(f"项目ID:{result['project_id']}")print(f"用户偏好:{result['loaded_memory']}")print(f"风险报告:{result['risk_report']}")print("="*60)

运行这个测试用例后,系统会按照以下流程执行:

加载A公司的长期记忆(首次运行使用默认偏好);主管Agent决策,调用条款抽取Agent抽取核心条款;条款抽取Agent调用工具,提取赔偿责任、终止条款、违约责任的摘要;主管Agent收到抽取结果后,调用风险评估Agent;风险评估Agent结合默认偏好(平衡),调用工具评估风险;评估完成后返回主管Agent,主管判断无高风险,触发长期记忆更新;流程结束,输出最终的风险报告。

如果我们将初始状态的loaded_memory改为"用户风险容忍度:保守,关注条款:[‘赔偿责任’],所属行业:金融",系统会评估出"赔偿责任上限50%"为中风险,并给出调整建议,整个流程会更贴合用户的个性化需求。

以上实现的是一个功能完备的原型系统,要投入工业级使用,还需要进行以下几方面的优化,确保系统的稳定性、性能和安全性:

工具优化:将模拟工具替换为真实的模型和API。比如条款抽取工具可以基于LegalBERT或行业大模型(如法研杯获奖模型)开发,合规性检查工具对接国家法律法规数据库API,提升抽取和评估的准确率。存储优化:将InMemoryStore替换为Redis或PostgreSQL,支持分布式部署和海量用户数据存储;将MemorySaver替换为RedisCheckpoint,支持跨服务的状态共享和恢复。性能优化:添加缓存机制,缓存常见条款的抽取结果和法律法规数据,减少重复计算;使用异步工具执行器,支持并行处理多个条款的抽取和评估,提升审核效率。安全性优化:对用户上传的合同文本进行脱敏处理,保护商业机密;添加权限控制,不同审核员只能查看自己负责的项目;记录所有Agent的操作日志,支持审计和追溯。扩展能力:增加更多专业化Agent,比如税务审核Agent(评估合同中的税务风险)、履行能力评估Agent(结合乙方资质评估履行风险);支持多种文件格式(PDF、Word)的上传和解析,提升用户体验。

通过LangGraph构建的智能合同审核系统,完美展现了多Agent架构的核心价值,将复杂任务拆解为专业化子任务,通过协作提升效率和准确率,同时结合记忆机制和人机协作,兼顾个性化和安全性。这套架构不仅适用于合同审核,还可以迁移到其他复杂场景,如代码审计、医疗诊断、金融风控等。

随着大模型技术的不断发展,多Agent系统将朝着更智能、更灵活、更易用的方向演进:一是Agent的自主决策能力会更强,能够自动调整协作流程,适应复杂场景的变化;二是跨模态协作会成为主流,Agent不仅能处理文本,还能结合图像、表格等多模态数据;三是低代码化,开发者可以通过可视化工具编排Agent流程,无需编写复杂代码。

来源:码韵匠道

相关推荐