每位 AI 工程师都必须构建的 30 个智能体——金融与法律领域智能体

0 阅读29分钟

衡量智能的标准,是改变的能力。
—— Albert Einstein

为金融和法律构建智能体,是一场完全不同的游戏。前几章中的通用架构还可以承受试错,但这些领域不行。在受监管领域中,一次合规失败并不只是产生一个糟糕答案。它可能触发罚款、制裁,甚至刑事责任。每一条建议都必须能追溯到其数据来源。每一个决策都必须经得起监管审计。每一次交互都必须记录足够细节,以便在数月或数年后重构当时的推理过程。本章中,你将构建两个生产级智能体:一个金融顾问智能体,它结合市场分析、风险评估和合规检查;一个法律智能智能体,它自动化合同分析、先例检索和引用验证。

在第 12 章建立了伦理与可解释性基础之后,我们现在可以考察一个信任不是靠有说服力的语言,而是靠严谨流程赢得的领域。金融建议位于不确定性、监管和个人后果的交叉点。金融智能体必须证明其假设的合理性,区分事实与预测,并保留一份可审计记录,说明每条建议是如何产生的。

本章将覆盖以下主题:

  • 金融顾问智能体
  • 法律智能智能体

技术要求

要运行本章中的示例,你需要准备以下内容:

  • Python 3.10 或更高版本
  • 以下 Python 包:langchain==0.2.16langchain-openai==0.1.23langchain-community==0.2.16langgraph==0.2.28openai==1.40.0yfinance==0.2.41finnhub-python==2.4.19tavily-python==0.3.3numpy==1.26.4pydantic==2.8.2python-dotenv==1.0.1
  • 一个 OpenAI API key,并具备访问 gpt-4o-mini 模型的权限
  • 一个 Finnhub API key,用于金融数据,finnhub.io 提供免费层
  • 一个 Tavily API key,用于新闻搜索能力,tavily.com

本章所有代码示例可在本书 GitHub 仓库中找到:

https://github.com/PacktPublishing/30-Agents-Every-AI-Engineer-Must-Build/chapter14

金融顾问智能体

金融服务行业长期拥抱数据驱动技术,但 agentic AI 代表着一次关键演进。金融机构服务数千名客户,这些客户拥有不同投资组合、风险承受能力和投资目标。人类顾问受时间和认知带宽限制,只能与一小部分客户保持深度关系。Agentic 系统通过自动化数据密集型顾问工作来扩展这种能力,同时将需要判断力的决策保留给人类监督。

本节将金融顾问智能体作为参考架构介绍,用于构建在市场波动和合规约束下运行的决策支持系统。目标不是自动化判断,而是结构化判断。我们将展示智能体如何通过受监督编排,将市场信号、客户上下文和策略规则结合起来,产生可解释、可质疑,并能在受监管环境中安全运营化的建议。

市场数据分析架构

金融顾问智能体的成败,取决于其市场数据管线。静态仪表盘告诉你昨天发生了什么。Agentic 系统需要感知现在正在发生什么,动态更新内部模型,并在时机消失之前调整建议。这要求一种架构,其中专门组件分别负责管线中的不同部分。

中心编排智能体会根据请求性质,将传入查询路由给专门子智能体。图 14.1 将金融顾问智能体呈现为一个受监督的多智能体系统,其中分析任务被拆解成专门角色,并通过显式控制层协调。

image.png

图 14.1——金融顾问智能体的多智能体架构,展示 supervisor agent 如何通过状态图路由协调专家智能体

在图 14.1 中,supervisor agent 既是入口点,也是策略感知编排器,决定调用哪个专家、调用顺序,以及每一步记录什么状态。状态图路由机制是关键架构防护。它将顾问流程变成一组可追踪的状态与转换序列,使系统能够执行工具权限、要求人工检查点,并为每条建议附加审计轨迹。

这种关注点分离简化了测试和审计。当监管者询问某条建议如何生成时,系统通过离散、可检查处理阶段追踪数据 lineage,而不是穿过一个单体推理链。

下面的代码实现了图 14.1 所示架构。该实现使用 LangGraph 的 StateGraph 定义智能体工作流。每个专家智能体都实现为一个 create_react_agent,并拥有领域专用工具。Supervisor 使用结构化输出,在每个决策点决定路由。下面的代码会配置 supervisor 路由 schema,定义智能体团队成员,并编译治理查询如何在专家智能体之间流转的 StateGraph

import os
from functools import partial
from typing import Annotated, Sequence, TypedDict, Literal
import yfinance as yf
from langchain_openai import ChatOpenAI
from langchain_core.prompts import (
    ChatPromptTemplate, MessagesPlaceholder
)
from langchain_core.messages import HumanMessage, BaseMessage
from pydantic import BaseModel
from langgraph.graph import END, START, StateGraph
from langgraph.prebuilt import create_react_agent
import operator

# LLM configuration
llm = ChatOpenAI(model="gpt-4o-mini-2024-07-18", temperature=0)

# Supervisor routing schema

导入完成后,下一段定义 supervisor 的路由 schema 和 prompt,指示它为每个查询选择合适的专家智能体:

class RouteResponse(BaseModel):
    next: Literal[
        "Market_Data_Agent",
        "Financial_Analysis_Agent",
        "News_Agent",
        "FINISH"
    ]

# Agent team members
members = ["Market_Data_Agent", "Financial_Analysis_Agent", "News_Agent"]

# Supervisor prompt
system_prompt = (
    "You are a Financial Services Supervisor managing: "
    f"{', '.join(members)}. "
    "Route queries to the appropriate specialist. "
    "Use Market_Data_Agent for price and volume data. "
    "Use Financial_Analysis_Agent for financial computations. "
    "Use News_Agent for market news and sentiment. "
    "Select FINISH when the query is fully resolved."
)
prompt = ChatPromptTemplate.from_messages([
    ("system", system_prompt),
    MessagesPlaceholder(variable_name="messages"),
    ("system", "Choose the next agent from: {options}.")
]).partial(options=str(members + ["FINISH"]))

supervisor_agent 函数会在每个决策步骤调用这条 chain,从结构化输出中提取路由决策,并将其作为状态更新返回,供 LangGraph 选择下一个节点:

def supervisor_agent(state):
    chain = prompt | llm.with_structured_output(RouteResponse)
    return {"next": chain.invoke(state).next}

市场数据智能体通过标准化 API 集成与外部金融数据供应商交互。在最简单形式中,该智能体封装 yfinance 库,以检索实时股票信息:

def get_market_data(query: str) -> str:
    """Retrieve current market data for a given stock symbol."""
    try:
        stock_symbol = query.strip().upper()
        ticker = yf.Ticker(stock_symbol)
        info = ticker.info
        current_price = info.get("currentPrice", "N/A")
        market_cap = info.get("marketCap", "N/A")
        pe_ratio = info.get("trailingPE", "N/A")
        day_high = info.get("dayHigh", "N/A")
        day_low = info.get("dayLow", "N/A")
        volume = info.get("volume", "N/A")
        return (
            f"Market Data for {stock_symbol}: "
            f"Price: ${current_price}, Market Cap: ${market_cap}, "
            f"P/E Ratio: {pe_ratio}, "
            f"Day Range: ${day_low}-${day_high}, "
            f"Volume: {volume}"
        )
    except Exception as e:
        return f"Error retrieving market data: {str(e)}"

该工具被包装进 create_react_agent,使市场数据智能体能够在 supervisor 更广泛编排循环中自行决定何时以及如何调用它:

market_agent = create_react_agent(
    llm, tools=[get_market_data],
    state_modifier="You are the Market Data Agent. "
    "Retrieve real-time stock data for client queries."
)

对于生产部署,Finnhub API 提供更稳健的数据源,包含基础财务数据、公司指标、实时报价和公司新闻等端点。下面的集成展示如何检索综合财务指标:

import finnhub

finnhub_client = finnhub.Client(
    api_key=os.getenv("FINNHUB_API_KEY")
)

def portfolio_analysis(query: str) -> str:
    """Fetch financial metrics using the Finnhub API."""
    try:
        symbol = query.split()[-1].upper()
        financials = finnhub_client.company_basic_financials(
            symbol, 'all'
        )
        metrics = financials.get('metric', {})
        return (
            f"Portfolio Analysis for {symbol}: "
            f"P/E Ratio: {metrics.get('peRatio')}, "
            f"Revenue Growth: {metrics.get('revenueGrowth')}, "
            f"52W High: {metrics.get('52WeekHigh')}, "
            f"52W Low: {metrics.get('52WeekLow')}"
        )
    except Exception as e:
        return f"Error: {str(e)}"

金融分析智能体在下游运行,消费市场数据智能体提供的原始数据,并应用量化模型得出可行动洞察。其分析管线会计算投资组合 beta、Sharpe ratio 和板块相关矩阵等指标。金融新闻智能体构成第三部分,通过 Tavily 等搜索式检索工具提供定性上下文,生成浓缩市场情报:

from langchain_community.tools.tavily_search import (
    TavilySearchResults
)

financial_news_tool = TavilySearchResults(max_results=5)

financial_news_agent = create_react_agent(
    llm, tools=[financial_news_tool],
    state_modifier="You are the Financial News Agent. "
    "Retrieve and summarize the latest financial news "
    "relevant to the user's query."
)

Supervisor 通过状态图编排这些专家。当客户问 “What is the current outlook for technology stocks?” 时,supervisor 会先路由到市场数据智能体获取价格,再路由到金融分析智能体获取板块指标,最后路由到新闻智能体获取评论。每个智能体完成任务后都会返回 supervisor,supervisor 会评估是否还需要额外智能体。这种 loop-until-complete 模式确保复杂的多来源查询在生成回应前得到完整解决:

# Workflow state
class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]
    next: str

# Wrap react agents as node-compatible callables
def agent_node(state, agent, name):
    result = agent.invoke(state)
    return {"messages": [HumanMessage(
        content=result["messages"][-1].content, name=name
    )]}

market_data_node = partial(
    agent_node, agent=market_agent, name="Market_Data_Agent"
)
# Similarly for analysis_node and news_node

# Build the state graph

将专家智能体包装为节点兼容 callable 后,下面这一段会组装 StateGraph,将每个智能体注册为命名节点,并定义路由边,使 supervisor 能够委派任务,并在每个专家完成后恢复控制:

workflow = StateGraph(AgentState)
workflow.add_node("Market_Data_Agent", market_data_node)
workflow.add_node("Financial_Analysis_Agent", analysis_node)
workflow.add_node("News_Agent", news_node)
workflow.add_node("supervisor", supervisor_agent)

# Route agents back to supervisor after completion
for member in members:
    workflow.add_edge(member, "supervisor")

# Conditional routing from supervisor
conditional_map = {m: m for m in members}
conditional_map["FINISH"] = END
workflow.add_conditional_edges(
    "supervisor", lambda x: x["next"], conditional_map
)
workflow.add_edge(START, "supervisor")

# Compile and execute

编译图会锁定拓扑并启用流式执行。下面的示例发送一个投资组合查询,并在查询流经 supervisor 和专家节点时打印每个状态更新:

graph = workflow.compile()
inputs = {
    "messages": [
        HumanMessage(content="Analyze the portfolio for AAPL.")
    ]
}
for output in graph.stream(inputs, stream_mode="values"):
    print(output)

这种顺序委派模式支持优雅降级:如果市场数据智能体遇到 API 超时,supervisor 可以路由到替代数据源,而不是中止整个工作流。

生产数据源

yfinance 库适合原型和演示,但不提供受监管金融环境所需的可靠性保证。生产系统应从 Bloomberg、Refinitiv(LSEG Data & Analytics)或 FactSet 等商业供应商获取市场数据,这些供应商提供合同 SLA 承诺、具备亚秒级延迟的实时数据源,以及数据质量控制。评估供应商时,应确认其覆盖所有所需资产类别、司法辖区数据权限,以及在生产负载下可持续的 API 速率限制。

到目前为止,该架构强调拆解和编排。这提升了清晰度和可追踪性,但并不保证安全。在金融领域,最有后果的失败往往不是信息缺失,而是不受控制的风险暴露、不适当建议,或在波动市场中未经质疑的假设。为解决这一缺口,我们将风险评估作为第一等架构层引入。风险评估智能体在同一个监督框架中运行,但贡献一个显式门控功能,将“看似合理的建议”转化为运营上可辩护的建议。

风险评估框架

风险评估是金融顾问智能体赢得或失去信任的地方。一个全面框架必须将市场风险、信用风险、流动性风险和运营风险编织在一起,并根据客户投资组合和风险承受能力的具体约束评估每一项。Agentic 方法将这一传统上人工、周期性流程转化为连续、自适应的监控系统。

四十五分钟,四亿四千万美元

2012 年 8 月 1 日,Knight Capital Group 向其自动交易系统部署了一次软件更新。一次配置错误重新激活了休眠代码,开始在 154 只股票上执行数百万笔非预期交易。45 分钟内,该公司累计了 70 亿美元错误头寸,并损失约 4.4 亿美元,几乎相当于其全部市值。Knight 通过紧急融资获救,但从未完全恢复,次年与 Getco LLC 合并。这一事件仍然是自动化金融系统的典型警告:没有防护的速度不是优势,而是负债。本章描述的每一道合规门、风险阈值和人工检查点,都是为了防止这种级联失败。

风险评估架构以三个递进阶段运行:专门智能体监控实时价格波动、交易量模式和情绪信号;统计模型将这些信号转化为校准风险分数;评分后的风险再映射到每位客户的投资画像上,生成个性化建议。这条管线不是单向的。建议阶段会将表现数据反馈到市场分析中,使模型随着条件变化持续优化。

在最基础形式中,风险评估智能体实现一种基于波动率的分类系统,根据近期价格变化幅度将仓位划入离散风险层级:

# Requires: import finnhub, os
# finnhub_client = finnhub.Client(api_key=os.getenv("FINNHUB_API_KEY"))

def risk_assessment(query: str) -> str:
    """Evaluate investment risk using real-time volatility metrics."""
    try:
        symbol = query.split()[-1].upper()
        quote = finnhub_client.quote(symbol)
        price_change = quote.get("dp", 0)
        if abs(price_change) > 5:
            risk_level = "High Risk"
        elif abs(price_change) > 2:
            risk_level = "Moderate Risk"
        else:
            risk_level = "Low Risk"
        return (
            f"Risk Assessment for {symbol}: "
            f"Price Change: {price_change}%, "
            f"Risk Level: {risk_level}"
        )
    except Exception as e:
        return f"Error: {str(e)}"

生产系统会在这一基线基础上加入更复杂的量化指标:Value at Risk(VaR),用于在给定置信水平下估计最大潜在损失;Conditional Value at Risk(CVaR),用于尾部风险估计;以及投资组合层面的相关性分析。下面的实现将年化波动率、最大回撤和 VaR 组合成一个综合评分:

关键风险指标

Value at Risk(VaR) 估计在给定时间范围和指定置信水平下的最大预期损失。例如,一天 95% VaR 为 10,000 美元,意味着有 5% 概率在单日内损失超过 10,000 美元。

Conditional Value at Risk(CVaR) 也称 expected shortfall,衡量超过 VaR 阈值之后最坏情形中的平均损失,因此对尾部风险更敏感。

年化波动率 表示收益标准差按一年周期缩放后的值,使不同资产之间的价格不稳定性可比较。

最大回撤 捕捉某段时间内从峰值到谷底的最大跌幅,反映投资者如果在峰值买入、谷底卖出所经历的最坏损失。

import numpy as np
# Requires: import yfinance as yf

class RiskScorer:
    """Multi-dimensional risk scoring for portfolio positions."""

compute_risk_score 方法将年化波动率、最大回撤和 VaR 按类初始化器中定义的权重组合为一个综合分数。然后它将该分数映射到一个分类风险区间:

    def compute_risk_score(self, symbol: str,
                           lookback_days: int = 90) -> dict:
        """Compute composite risk score incorporating
        volatility, drawdown, and VaR metrics."""
        ticker = yf.Ticker(symbol)
        hist = ticker.history(period=f"{lookback_days}d")
        returns = hist['Close'].pct_change().dropna()

        # Annualized volatility
        volatility = returns.std() * np.sqrt(252)

        # Maximum drawdown
        cumulative = (1 + returns).cumprod()
        rolling_max = cumulative.cummax()
        drawdown = (cumulative - rolling_max) / rolling_max
        max_drawdown = drawdown.min()

        # Value at Risk (95% confidence)
        var_95 = np.percentile(returns, 5)

        # Composite risk score (0-10 scale)
        vol_score = min(volatility / 0.05, 10)
        dd_score = min(abs(max_drawdown) / 0.05, 10)
        var_score = min(abs(var_95) / 0.03, 10)
        composite = (
            0.4 * vol_score +
            0.35 * dd_score +
            0.25 * var_score
        )

        return {
            "symbol": symbol,
            "annualized_volatility": round(volatility, 4),
            "max_drawdown": round(max_drawdown, 4),
            "var_95": round(var_95, 4),
            "composite_risk_score": round(composite, 2),
            "risk_category": self._categorize(composite)
        }

    @staticmethod
    def _categorize(score: float) -> str:
        if score >= 7.0:
            return "HIGH"
        elif score >= 4.0:
            return "MODERATE"
        return "LOW"

综合分数随后进入客户风险承受能力调整层。一个关键设计决策是在哪里执行风险限制。在合规架构中,执行发生在 supervisor 层,而不是单个智能体内部。在 supervisor 将建议路由给客户之前,它必须先经过验证门,检查综合风险分数是否符合客户风险承受能力。这呼应了第 12 章中的合规智能体架构:

def assess_risk(stock_symbol: str, composite_score: float,
                client_risk_tolerance: str) -> dict:
    """Evaluate risk level adjusted for client tolerance.
    Consumes the composite_risk_score from RiskScorer."""
    # Map composite score to risk category

assess_risk 后半部分会将该风险类别根据客户声明的风险承受能力进行调整,生成同时反映市场条件和个人约束的个性化风险区间:

if composite_score >= 7.0:
        market_risk = "HIGH"
    elif composite_score >= 4.0:
        market_risk = "MODERATE"
    else:
        market_risk = "LOW"

    # Adjust for client risk tolerance
    tolerance_map = {
        "conservative": {
            "HIGH": "UNACCEPTABLE",
            "MODERATE": "HIGH",
            "LOW": "MODERATE"
        },
        "moderate": {
            "HIGH": "HIGH",
            "MODERATE": "MODERATE",
            "LOW": "LOW"
        },
        "aggressive": {
            "HIGH": "MODERATE",
            "MODERATE": "LOW",
            "LOW": "LOW"
        }
    }
    adjusted_risk = tolerance_map.get(
        client_risk_tolerance, {}
    ).get(market_risk, market_risk)

    return {
        "symbol": stock_symbol,
        "market_risk": market_risk,
        "client_risk_tolerance": client_risk_tolerance,
        "adjusted_risk": adjusted_risk
    }

真正力量在于反馈循环。当风险评估智能体发现投资组合漂移超出客户舒适区时,它会向 supervisor 发送再平衡建议,supervisor 可以将其呈现给客户;在完全自主配置中,也可以直接执行交易。传统审查周期往往数周或数月后才捕获漂移。这个架构可以实时捕获它。

有了风险评估后,下一小节会将这些信号应用到个人客户画像上,生成个性化财务计划。

个性化财务规划

个性化财务规划需要智能体维护丰富、纵向的个人客户模型。这映射第 5 章的记忆架构:工作记忆用于活跃会话上下文,情节记忆用于交互历史,语义记忆用于持久画像信息。在金融顾问场景中,个性化不是锦上添花,而是必要条件。证券监管要求建议必须适合特定客户。

个性化规划智能体整合并行处理网络:一个面向客户的服务层,处理查询、画像和回应生成;同时还有一个合规层,执行监管审查、文档化和审计日志。行业实现已经展示出可衡量改善:

下表总结了部署 AI 驱动个性化的零售金融机构所报告的代表性表现结果,对比了实现前后关键顾问指标。

MetricBefore AIAfter AI
Response time平均 4 小时30 秒
Compliance accuracy95%99.99%
Client capacity每位顾问 100 人每位顾问 1,000 人或更多
Monthly revenue$8,000$25,000

表 14.1——AI 驱动个性化在零售金融顾问中的表现影响

下面的实现展示核心画像检索和上下文化逻辑,并将合规验证集成在数据访问层:

class ClientProfileAgent:
    """Retrieves and contextualizes client financial
    profiles for personalized advisory responses."""

    def __init__(self, memory_store, compliance_validator):
        self.semantic_memory = memory_store
        self.compliance = compliance_validator

get_contextualized_profile 方法检索存储的客户画像,并用当前市场数据、合规约束和近期交互历史对其增强,生成下游顾问节点消费的上下文对象:

    def get_contextualized_profile(
        self, client_id: str, query_context: str
    ) -> dict:
        """Retrieve client profile with context-relevant
        financial history."""
        # Retrieve durable profile from semantic memory
        profile = self.semantic_memory.retrieve(
            entity_id=client_id,
            memory_type="semantic"
        )

        # Retrieve relevant interaction history
        episodes = self.semantic_memory.retrieve(
            entity_id=client_id,
            memory_type="episodic",
            query=query_context,
            top_k=10
        )

        # Validate data access against compliance rules
        filtered_profile = (
            self.compliance.filter_accessible_data(
                profile=profile,
                query_context=query_context,
                access_level="advisory"
            )
        )

        return {
            "profile": filtered_profile,
            "relevant_history": episodes,
            "risk_tolerance": profile.get("risk_tolerance"),
            "investment_horizon": profile.get(
                "investment_horizon"
            ),
            "regulatory_constraints": profile.get(
                "constraints", []
            )
        }

合规验证器位于数据访问层,而不是事后补上。基于第 12 章的伦理推理框架,该模式确保个性化永远不会损害监管合规。每次数据检索都会被记录,以供审计。

实践执行使用 LangGraph 状态机中的自我纠正循环。任何建议到达客户之前,必须通过合规节点。如果失败,该建议会被修订并重新验证:

from langgraph.graph import StateGraph, END

class AdvisoryState(TypedDict):
    messages: list
    client_profile: dict
    recommendation: dict
    compliance_result: dict
    final_response: str

def validate_compliance(state: AdvisoryState):
    """Validate recommendation against
    regulatory requirements."""
    rec = state["recommendation"]
    profile = state["client_profile"]
    issues = []

    # Suitability check
    if rec["risk_score"] > profile["max_risk_tolerance"]:
        issues.append(
            "SUITABILITY: Recommendation risk "
            "exceeds client tolerance"
        )

    # Concentration check
    for asset, weight in rec["allocation"].items():
        max_conc = policy_rules.get("max_concentration", 0.25)        if weight > max_conc:
            issues.append(
                f"CONCENTRATION: {asset} weight "
                f"{weight:.0%} exceeds {max_conc:.0%} limit"
            )

    return {
        "compliance_result": {
            "passed": len(issues) == 0,
            "issues": issues
        }
    }

def route_after_compliance(state: AdvisoryState):
    if state["compliance_result"]["passed"]:
        return "deliver"
    return "revise"

# Build workflow with compliance gate

定义处理函数之后,下面的片段会组装顾问 StateGraph,将合规门连接为条件分支,并编译可执行工作流:

workflow = StateGraph(AdvisoryState)
workflow.add_node("recommend", generate_recommendation)
workflow.add_node("comply", validate_compliance)
workflow.add_node("deliver", deliver_to_client)
workflow.add_node("revise", revise_recommendation)
workflow.add_edge("recommend", "comply")
workflow.add_conditional_edges(
    "comply", route_after_compliance,
    {"deliver": "deliver", "revise": "revise"}
)
workflow.add_edge("revise", "comply")  # Re-validate
workflow.add_edge("deliver", END)

revise 节点会回到合规验证,创建自我纠正循环,一直持续到建议满足所有监管约束。这就是 compliance-by-architecture,即架构内生合规:结构上不可能让不合规建议到达客户。

案例研究:面向零售投资者的投资顾问

为了将这些概念落到具体实现中,考虑 RetailAdvisor,这是为无法获得专属财富管理服务的零售投资者构建的投资顾问智能体。该系统将前面描述的市场数据分析、风险评估和个性化规划架构整合为一个统一、层级化、多智能体系统。

一个 supervisor agent 协调五个专家:onboarding agent 负责进行风险画像访谈并将客户画像持久化到语义记忆;market intelligence agent 持续监控与客户投资组合相关的条件;portfolio construction agent 应用现代投资组合理论生成多元化配置;risk monitoring agent 执行持续多维评分;compliance agent 使用第 12 章中的合规注册表模式,验证所有建议是否符合适用法规。

Onboarding agent 会建立客户投资周期、风险承受能力、财务目标和监管约束。该画像被持久化到语义记忆中,并影响所有后续交互。Portfolio construction agent 不只考虑理论最优配置,还考虑实际约束:交易成本、税务影响和最低投资门槛。

下面是一次代表性交互:一名零售投资者问:“I have $50,000 to invest and want moderate growth over the next ten years. What should I do?” Supervisor 会路由给 portfolio construction agent,后者会向 market intelligence 查询当前条件,并向 risk monitoring 查询板块层级评估。基于中等风险承受能力和十年周期,它生成一个多元化配置:45% 美国股票(通过低成本指数基金)、20% 国际股票、25% 固定收益和 10% 另类投资。交付之前,compliance agent 会验证适当性、多元化和监管完整性。

智能体之间的通信协议遵循标准化 JSON 格式,携带路由和审计所需元数据:

{
    "sender_id": "portfolio_construction_agent",
    "recipient_id": "compliance_agent",
    "message_type": "recommendation_validation_request",
    "timestamp": "2025-01-15T14:30:00Z",
    "confidence_score": 0.87,
    "data_payload": {
        "client_id": "retail_client_4521",
        "recommendation_type": "initial_allocation",
        "asset_allocation": {
            "us_equities": 0.45,
            "international_equities": 0.20,
            "fixed_income": 0.25,
            "alternatives": 0.10
        },
        "risk_score": 6.2,
        "expected_annual_return": 0.078,
        "max_drawdown_estimate": -0.18
    },
    "context_references": [
        "risk_profile_4521",
        "market_analysis_20250115"
    ],
    "requires_response": true,
    "priority_level": "high"
}

该格式中的每条消息都会被持久化到不可变审计日志中。当监管者询问为何给出某条具体建议时,系统会从数据摄取到分析再到合规验证,重构完整推理链。这种可追踪性使该系统适合部署到受监管环境中。

行业先行者已经在规模化探索这些模式。JPMorgan Chase 已经投资于 AI 驱动的市场研究摘要、用于客户询问的自然语言理解,以及能够标记高风险顾问模式的合规监控。Virgin Money 的 Redi agent 展示了 agentic 系统如何超越静态 FAQ,基于上下文感知个性化,处理涉及交易历史和账户关联决策的细致金融问题。

金融顾问智能体展示了当风险可测量时,智能体如何赢得信任:波动率分数、集中度限制和适当性阈值,提供了清晰的通过/失败标准。法律领域更难。风险无法被还原为一个数字。法律智能体必须围绕语言推理,而相同词语会因上下文、司法辖区和来源权威而承载不同分量。

法律智能智能体

这里的风险与金融类似,但失败模式不同。不准确的法律解释可能损害案件结果。伪造引用可能给依赖它们的律师带来职业制裁。法律推理的复杂性依赖于围绕事实模式和层级权威结构的类比推理,因此需要远超标准检索增强生成的专门架构。

本节考察让智能体能够导航这些挑战的架构基础,从知识库设计,到先例分析,再到合同审查,最终到完整的法律研究和法律文书准备工作流。

法律知识库集成

任何法律智能智能体的基础,都是它的知识库:一个结构化、可搜索的法律、法规、判例法和评论库。不同于通用检索系统,法律知识库必须保留权威之间的层级关系,维持 binding 与 persuasive precedent、primary 与 secondary sources、current law 与 superseded provisions 之间的区别。

核心设计张力在于,法律推理同时依赖概念相似性和精确文本引用。混合搜索策略通过结合 dense vector retrieval 和 sparse keyword matching 来解决这一点。前者即使术语不同也能找到相关先例,后者能精确检索特定引用和法规编号。

下面的实现展示了一个带有混合检索和权威加权排序的法律知识库:

class LegalKnowledgeBase:
    """Legal knowledge base with hierarchical authority
    tracking and hybrid retrieval."""

    def __init__(self, vector_store, embedding_model):
        self.store = vector_store
        self.embedder = embedding_model

ingest_case 方法会将每份判例文档编码进向量存储,并附带结构化元数据,以捕获法院层级、司法辖区和权威等级:

    def ingest_case(self, case: dict):
        """Ingest a case with structured authority metadata."""
        embedding = self.embedder.encode(case["text"])
        metadata = {
            "case_name": case["name"],
            "citation": case["citation"],
            "court": case["court"],
            "jurisdiction": case["jurisdiction"],
            "date": case["date"],
            "authority_level": self._classify_authority(
                case["court"]
            ),
            "status": case.get("status", "good_law"),
            "legal_issues": case.get("issues", []),
            "key_holdings": case.get("holdings", [])
        }
        self.store.upsert(
            id=case["citation"],
            embedding=embedding,
            metadata=metadata
        )

hybrid_search 方法是 LegalKnowledgeBase 的检索核心。它将语义相似性与权威加权排序结合起来,为给定查询浮现最相关且最具法律权威性的来源:

    def hybrid_search(self, query: str,
                      jurisdiction: str = None,
                      min_authority: int = 0) -> list:
        """Hybrid search combining semantic similarity
        with authority-weighted ranking."""
        query_embedding = self.embedder.encode(query)
        filters = {}
        if jurisdiction:
            filters["jurisdiction"] = jurisdiction
        if min_authority > 0:
            filters["authority_level"] = {
                "$gte": min_authority
            }

        results = self.store.query(
            embedding=query_embedding,
            filter=filters,
            top_k=50
        )

初始检索之后,该方法会通过混合语义相似度分数、权威权重和新近性 boost 对结果重新排序,产生偏好 binding、recent authority 的最终排序:

        # Re-rank by combining semantic score
        # with authority weight
        for result in results:
            authority_boost = (
                result.metadata["authority_level"] / 10.0
            )
            recency_boost = self._recency_score(
                result.metadata["date"]
            )
            result.final_score = (
                0.5 * result.similarity_score +
                0.3 * authority_boost +
                0.2 * recency_boost
            )

        return sorted(
            results,
            key=lambda x: x.final_score,
            reverse=True
        )

在检索层之上,会应用领域特定排序逻辑。最高法院判决优先于地区法院裁决。较新法规会取代较旧的冲突条款。来自相关司法辖区、且直接相关的 holding,比其他地方的说服性权威更重要。最终分数中的权重分布,即语义相似度 0.5、权威等级 0.3、新近性 0.2,反映了概念相关性在法律研究中的首要性:一个语义上相关但权威较低的来源,比一个权威很高但只是在边缘问题上相关的来源更有用。权威和新近性更像是平局裁决因素,而不是主要信号;当领域政策或客户偏好需要不同比例时,这些权重可以配置调整。这些规则被编码在复合排序函数中的 authority_levelrecency_score 组件中。

下一小节将这些检索和推理能力应用到合同审查中,展示法律智能智能体如何使用顺序管线结构化分析复杂法律文档。

案件分析与先例查找

识别并分析相关法律先例,也许是法律智能体必须具备的最具智力挑战的能力。它要求理解争议中的法律问题,找到处理类似问题的案件,评估这些推理是否适用于当前事实,并将所有内容综合成连贯论证。

当 AI 引用不存在的案件

2023 年 6 月,纽约律师 Steven Schwartz 成为震动法律界的新闻人物。他使用 ChatGPT 研究一起人身伤害案件,而模型生成的法律文书中充满了自信且格式正确的案件引用,例如 Varghese v. China Southern Airlines 和 Martinez v. Delta Airlines。但这些案件根本不存在。法院制裁了 Schwartz 和他的律所。几个月内,美国各地法院开始发布常设命令,要求律师披露 AI 使用情况,并亲自核实每一条 AI 生成引用。这生动说明了为什么在任何法律 AI 管线中,引用验证都不是锦上添花,而是职业生存要求。

先例查找管线分三个阶段运行,如图 14.2 所示。

image.png

图 14.2——法律智能智能体基于 RAG 的案件分析工作流,展示法律先例的检索、验证和综合

图 14.2 中的管线通过三个专门阶段,应对法律先例查找中的结构和语义复杂性。

阶段 1——问题提取:该过程首先使用 LLM 的自然语言理解能力,将一个多面向法律事项拆解为离散、可管理问题。这确保检索查询针对具体法定义务或过失构成要件,而不是宽泛、含糊主题。

阶段 2——多维检索:一旦问题被定义,系统会启动并行检索策略,包括基于判例 embedding 的语义匹配、基于司法辖区层级的权威搜索,以及基于事实模式分析的类比推理。

阶段 3——综合与验证:最后阶段评估检索到的权威在适用性和分量上的价值。核心是 Citation Verification Gate,它会将每条检索引用与权威知识库交叉核对。这一严格步骤是防御幻觉先例的主要机制,确保只有 “good law” 进入最终法律文书。

在实践中,问题提取阶段会将复杂问题拆解为组成元素。一个关于 “liability for data breaches in healthcare settings” 的查询会生成离散问题:适用注意义务标准、过失构成要件、HIPAA 义务和可用抗辩。每个问题都会驱动一条独立检索查询:

class PrecedentFinder:
    """Identifies and analyzes relevant legal precedent
    through multi-dimensional retrieval."""

    def __init__(self, legal_kb, llm):
        self.knowledge_base = legal_kb
        self.llm = llm

find_precedents 方法编排三阶段管线。它提取离散法律问题,通过并行语义和引用搜索检索候选项,并按权威权重和事实相关性排序合并结果:

    def find_precedents(self, legal_matter: dict) -> list:
        """Execute the full precedent finding pipeline."""
        # Stage 1: Extract discrete legal issues
        issues = self._extract_issues(legal_matter)

法律问题识别后,阶段 2 会同时在语义索引和引用索引中启动并行检索,将结果合并为统一候选集:

        # Stage 2: Multi-dimensional retrieval
        candidates = []
        for issue in issues:
            semantic_results = (
                self.knowledge_base.hybrid_search(
                    query=issue["description"],
                    jurisdiction=legal_matter.get(
                        "jurisdiction"
                    ),
                    min_authority=3
                )
            )
            citation_results = (
                self.knowledge_base.citation_search(
                    statutes=issue.get(
                        "relevant_statutes", []
                    ),
                    top_k=10
                )
            )
            merged = self._merge_results(
                semantic_results, citation_results
            )
            candidates.extend(merged)

在通过语义搜索和引用搜索检索到候选先例后,最终阶段会先按权威和事实相关性排序,再返回给调用方:

        # Stage 3: Analyze and rank precedents
        analyzed = self._analyze_precedents(
            candidates, legal_matter
        )
        return self._rank_by_authority_and_relevance(
            analyzed
        )

class LegalIssue(BaseModel):
    description: str
    category: str
    priority: int = 1  # 1 (high) to 3 (low)

class IssueList(BaseModel):
    issues: List[LegalIssue]

_extract_issues helper 会使用 LLM 将非结构化法律事项描述拆解为离散、带类型的问题。它在返回之前根据 IssueList schema 验证输出,确保下游管线阶段收到结构良好的数据:

    def _extract_issues(self, matter: dict) -> list:
        """Decompose a legal matter into discrete
        legal issues for targeted retrieval."""
        prompt = f"""Analyze the following legal matter
        and identify the discrete legal issues that
        must be resolved. For each issue, provide:
        1. A concise description
        2. The area of law involved
        3. Any relevant statutes or regulations
        4. Key factual elements that determine
           applicability

        Legal Matter: {matter['description']}
        Jurisdiction: {matter['jurisdiction']}
        """
        response = self.llm.generate(prompt)
        raw = self._parse_issues(response)        return IssueList(issues=raw).issues

这种多维方法显著降低遗漏相关先例的风险。语义相似性识别概念上对齐的权威,引用网络分析浮现经常共同引用的案件,事实模式匹配则找到情境类似案件。

合同分析框架

合同分析结合了结构化文档处理和条款层面的法律语义推理。合同分析智能体必须解析复杂结构,分类单个条款,评估风险,标记非标准条款,并生成突出需要律师关注区域的摘要。

该框架以顺序管线加并行验证的方式运行,如图 14.3 所示。

image.png

图 14.3——端到端合同分析框架

图 14.3 将合同分析呈现为一个工程化工作流。管线经过文档摄取、条款提取、风险标记、合规验证和结构化摘要生成几个阶段。关键架构点是:合规验证会在每个阶段并行作为 gate 运行,而不是作为后处理步骤。这使系统能够尽早拒绝不安全输出,并在摘要到达律师之前确保必需条款存在。

class ContractAnalysisAgent:
    """Analyzes legal contracts through a multi-stage
    pipeline with compliance validation."""

    def __init__(self, llm, clause_classifier,
                 risk_matrix, compliance_rules):
        self.llm = llm
        self.classifier = clause_classifier
        self.risk_matrix = risk_matrix
        self.compliance = compliance_rules

analyze_contract 方法编排完整管线:摄取文档,提取并分类条款,标记风险,并行运行合规验证,然后组装面向律师审查的结构化输出:

    def analyze_contract(self, document: str,
                         context: dict) -> dict:
        """Execute full contract analysis pipeline."""
        # Stage 1: Document structure extraction
        structure = self._parse_document_structure(
            document
        )

        # Stage 2: Clause extraction and classification
        clauses = []
        for section in structure["operative_sections"]:
            extracted = self.classifier.classify(section)
            clauses.extend(extracted)

条款被提取和分类后,管线进入风险评估。每个条款都会根据司法辖区感知风险矩阵评分,只有 HIGH 或 CRITICAL 等级发现会被浮现给律师审查:

        # Stage 3: Risk assessment per clause
        risk_findings = []
        for clause in clauses:
            risk = self.risk_matrix.evaluate(
                clause_type=clause["type"],
                clause_text=clause["text"],
                reviewing_party=context.get(
                    "reviewing_party"
                ),
                jurisdiction=context.get("jurisdiction")
            )
            if risk["level"] in ["HIGH", "CRITICAL"]:
                risk_findings.append({
                    "clause": clause,
                    "risk": risk,
                    "recommendation": (
                        risk["suggested_action"]
                    )
                })

收集风险发现后,最后阶段会根据适用法规验证完整条款集,并生成面向律师审查的结构化摘要:

        # Stage 4: Compliance validation
        compliance_issues = self.compliance.validate(
            clauses=clauses,
            applicable_regulations=context.get(
                "regulations", []
            )
        )

        # Stage 5: Summary generation
        summary = self._generate_summary(
            structure, clauses,
            risk_findings, compliance_issues
        )

        return {
            "structure": structure,
            "clauses": clauses,
            "risk_findings": risk_findings,
            "compliance_issues": compliance_issues,
            "summary": summary
        }

下面的案例研究将检索、先例排序和引用验证组件整合成一个单一可工作系统。LegalBrief 是一个诉讼支持助手,它从律师提供的事实摘要中检索治理性先例,评估客户立场强度,并生成带格式化引用的结构化研究备忘录。它展示法律智能智能体的各项能力如何在真实案件条件下组合成端到端工作流。

案例研究:法律研究和法律文书准备助手

LegalBrief 是面向诉讼律师的法律研究和法律文书准备助手。它结合上文基于 RAG 的检索架构与多阶段文档生成,生成研究备忘录和法律文书草稿。该系统采用带嵌入式质量门的五阶段顺序工作流,并实现为 LangGraph 状态机。

当律师提交类似 “What is the current standard for establishing personal jurisdiction over foreign corporations in e-commerce disputes under the Ninth Circuit?” 这样的问题时,系统会经过五个阶段:问题拆解;从 binding authority 扩展到 persuasive authority 的多维检索;法理分析,识别巡回法院之间的分歧和最强权威;带恰当引用格式的结构化备忘录起草;以及引用准确性验证。

引用验证不可协商。幻觉案例法是 AI 辅助法律研究中最危险的单一失败模式。在法院文件中引用伪造案件,承担后果的是律师,而不是算法。系统通过将草稿中的每一条引用与权威知识库交叉核对来防御这一点,并标记任何无法验证的内容。

class LegalResearchState(TypedDict):
    query: str
    jurisdiction: str
    issues: list
    precedents: list
    analysis: dict
    draft: str
    citations_verified: bool
    quality_score: float

该状态 schema 捕获研究查询的完整生命周期。下面函数实现每个管线阶段,从问题拆解和多维检索开始:

def decompose_issues(state: LegalResearchState):
    """Stage 1: Break research question into
    discrete legal issues."""
    issues = llm.extract_legal_issues(
        state["query"], state["jurisdiction"]
    )
    return {"issues": issues}

def retrieve_precedents(state: LegalResearchState):
    """Stage 2: Multi-dimensional retrieval."""
    all_precedents = []
    for issue in state["issues"]:
        results = legal_kb.hybrid_search(
            query=issue["description"],
            jurisdiction=state["jurisdiction"],
            min_authority=3
        )
        all_precedents.extend(results)
    return {"precedents": deduplicate(all_precedents)}

检索之后,管线必须在引用进入草稿前验证每一条引用。verify_citations 函数会将每条引用权威与知识库交叉核对,检查司法辖区、先例状态,以及该案件是否仍是 good law:

def verify_citations(state: LegalResearchState):
    """Stage 5: Cross-reference every citation"""
    citations = extract_citations(state["draft"])
    verified = 0
    for citation in citations:
        exists = legal_kb.verify_citation(
            citation["text"]
            jurisdiction=citation.get("jurisdiction"),            check_precedential=True,            check_good_law=True,        )
        if exists:
            verified += 1
        else:
            state["draft"] = flag_unverified(
                state["draft"], citation
            )
    return {
        "citations_verified": verified == len(citations),
        "quality_score": verified / max(len(citations), 1)
    }

# Build the pipeline

定义处理函数后,下面这段会组装 LegalResearchState 图,连接五个顺序阶段,并编译可执行管线:

workflow = StateGraph(LegalResearchState)
workflow.add_node("decompose", decompose_issues)
workflow.add_node("retrieve", retrieve_precedents)
workflow.add_node("analyze", analyze_authorities)
workflow.add_node("draft", generate_draft)
workflow.add_node("verify", verify_citations)
workflow.add_edge(START, "decompose")
workflow.add_edge("decompose", "retrieve")
workflow.add_edge("retrieve", "analyze")
workflow.add_edge("analyze", "draft")
workflow.add_edge("draft", "verify")
workflow.add_edge("verify", END)
legal_research_graph = workflow.compile()

系统会标记任何无法验证的引用,在输出中清楚区分已验证和未验证权威。这种透明性让律师能够将人工验证精力集中在最重要的地方。

在典型合同争议工作流中,律师提供事实背景和关键问题。LegalBrief 检索治理原则和相关先例,分析客户立场强度,并生成带格式化引用的法律文书草稿。律师负责审阅和定稿,将专业能力集中在战略论证上,而智能体处理劳动密集型研究。

这种分工呼应本章更广泛主题:在受监管领域中,智能体最有效的角色不是自主决策者,而是力量倍增器;它们放大人类专业人士能力,同时维持问责。

小结

本章展示了本书中逐步建立的智能体工程模式,如何在两个最严苛应用领域中汇合:金融顾问和法律智能。这两个领域都施加了更宽松语境中不存在的硬约束。

金融顾问智能体必须满足适当性要求,生成可审计建议轨迹,并执行客户特定风险限制。多智能体 supervisor 架构,结合持续风险监控和架构内生合规验证门,提供了结构基础。法律智能智能体必须生成可验证引用,导航司法辖区层级,并生成符合法律专业标准的结构化分析。混合检索架构、多维先例查找和引用验证阶段,回应了法律推理在非结构化文本上的独特挑战。

使这些领域获得成功的模式,是前几章中探索过的多智能体协调、记忆管理、检索增强生成和合规推理的进一步精炼。区别在于严谨性。在受监管行业中,合规不是智能体正确工作之后再添加的功能,而是一项从一开始就塑造每个设计决策的架构约束。

当你将这些架构扩展到其他受监管领域时,无论医疗、保险还是政府服务,核心原则始终不变:构建不仅有能力,而且可问责的智能体。每一条建议都必须可追踪。每一个决策都必须可审计。每一次交互都必须被记录。

下一章中,我们将探索教育和知识智能体,考察智能体如何个性化学习,综合知识库,并支持跨学术和专业领域的复杂推理。