首页 / 文章 / 产品实验中的工具变量:在Python中消除LLM路由决策的混杂
← 返回
IT技术

产品实验中的工具变量:在Python中消除LLM路由决策的混杂

✍️ zhirenhun 📅 2026/8/4 👁 212 阅读 ⏱ 53 分钟
产品实验中的工具变量:在Python中消除LLM路由决策的混杂

对于负责管理多模型网关的数据科学领导者和产品经理来说,衡量模型质量的标准回归方法存在根本性缺陷。

无论你是否承认,你其实都在进行一项因果推断实验,而你的路由规则正在悄无声息地污染你的性能估计。

考虑这样一个网关:它根据置信度阈值将传入的查询路由到高级模型或更快、更便宜的替代模型。置信度得分低于某个阈值的查询会被路由到高级模型,而高于该阈值的查询则走廉价模型。

你拉取日志,将task_completed对路由决策做回归,发现高级路由带来了14个百分点的提升。基于这个数字,你的基础设施团队可能会开始起草一份将全部流量路由到高级模型的提案。

在发出那份提案之前,请先停下来。路由规则与查询复杂度高度相关,而查询复杂度直接决定任务是否完成。复杂的查询更难处理,失败率也更高,无论由哪个模型来处理都是如此。

当你将任务完成情况对高级路由做回归时,你同时测量了两个纠缠在一起的现象:将查询发送到高级模型的因果效应,以及每个模型收到的查询在难度上的固有差异。

标准回归会将这两个信号混合成一个系数,而观察到的提升既反映了查询难度,也同样反映了模型质量。

只要分配与查询特征相关,路由混杂就会存在,而任何正常工作的路由系统都会如此。分配规则确保两个处理组中包含系统性不同的查询,从而使朴素的比较作为因果估计失效。

工具变量分析是打破这一僵局的方法。你需要一个第三个变量,它出于与查询质量完全无关的原因影响路由。

限流触发的回退正是这样的变量。当高级模型达到限流阈值时,网关会将查询重新路由到更便宜的模型,而不管查询的特征如何。限流是由于基础设施原因而触发的,与用户实际提出的问题无关。这种随机性就是一个工具,而两阶段最小二乘法(2SLS)让你能够从中提取出干净的因果估计。

本教程将带你走完从诊断到修复的完整流程(使用Python):为什么路由混杂会使OLS产生偏误,如何通过两个链式回归从零构建2SLS,如何用第一阶段F统计量检查工具强度,以及如何恢复2SLS实际估计的局部平均处理效应,而不是误将其当作平均处理效应。最后,你将知道如何在自己的日志中识别出混杂的路由决策,如何从限流回退这类基础设施信号中构建有效的工具变量,以及如何生成置信区间大小合适的因果估计——而不是使用手动2SLS默认给出的过度自信的区间。

配套笔记本:本文中的每个代码块都可以在配套仓库的iv_demo.ipynb中端到端运行,仓库地址为github.com/RudrenduPaul/product-experimentation-causal-inference-genai-llm/tree/main/11_instrumental_variables/

目录

为什么路由会混淆回归

路由系统会做出一个相关的决策。低置信度分数、长令牌数或复杂多步意图的查询会被路由到高级模型。简短、清晰且完全在廉价模型能力范围内的查询会被路由到廉价模型。这种相关性正是路由层的意义所在。

问题在于,驱动路由决策的相同特征也会影响您关心的结果。

对于复杂查询,无论由哪个模型处理,任务完成都更难。当您编写 task_completed ~ routed_to_premium + controls 时,controls 项可以吸收复杂性的可观测维度:查询长度、用户参与层级以及您记录的任何内容。

不可观测的维度仍然嵌入在 routed_to_premium 系数中,它们会使估计向下偏(复杂查询路由到高级模型后完成率较低,使高级模型看起来比实际更差)或向上偏,具体取决于混杂的方向。

在本教程使用的合成数据集中,OLS估计值为+3.3个百分点,而真实因果效应为+6个百分点。这是完全由未观测到的查询复杂性驱动的2.7个百分点的向下偏误。

回归看起来很有信心,p值看起来显著,标准OLS输出中没有任何标记出问题。这就是这种失败模式危险的原因:它在标准回归诊断中是不可见的。

2SLS正是为这种结构而构建的。您需要路由中与查询质量无关的外部变异来源。速率限制触发的回退提供了这一点。

dcb88e06-c217-47f7-b220-a3c3184c84e1

图1:IV因果结构。工具变量(Z = 速率限制回退)满足相关性(Z预测路由)、排他性(不存在从Z到结果的直接路径)和独立性(Z与未观测的查询复杂性不相关)。红色虚线箭头显示了导致朴素OLS产生偏误的混杂路径。

什么是工具变量

工具变量是一个能够改变您内生变量(路由决策)的变量,且它到您的结果(任务完成)之间没有任何其他直接路径。

有效工具变量由四个假设定义。

相关性

工具变量必须实际影响内生变量。一个在15%符合高级条件的查询上触发的速率限制回退指示器,将显著影响这些查询是否被路由到高级模型。

这一假设是可检验的:使用第一阶段F统计量进行验证。常规阈值为F > 10,由Staiger和Stock(1997)确立,对应在最坏情况下,2SLS估计量相对OLS的最大偏差约为10%。

请注意,Andrews、Stock和Sun(2019)的更新研究指出,在样本量较小或多个工具变量的情境下,该阈值可能过于宽松。对于备选数据有限的生产分析,应将F > 10视为最低下限,并在报告结果前通过额外的敏感性检验加以验证。若F值低于10,则工具变量明显较弱,估计结果不可靠。

排他性约束

工具变量必须仅通过其对路由的影响来影响结果。限流回退通过改变处理查询的模型来完全完成任务,不存在其他独立的直接路径。

这一假设需要基于逻辑的业务推理,无法仅从数据中验证。由总体基础设施负载触发的回退与用户所问内容或任务难度无关。

独立性

工具变量必须独立于所有混杂因素。限流事件由总体API流量驱动,与任何单个查询的特征无关。给定查询触发限流回退的概率与查询复杂度、用户层级或任何其他混杂因素不相关。这一假设同样需要从逻辑上进行论证。

单调性

工具变量必须使所有受影响的单元朝同一方向移动。对于限流回退,每个受影响的查询都会从高级模型切换到廉价模型,但没有任何查询会因回退而从廉价模型切换到高级模型。这排除了违抗者,也是LATE解释成立的必要条件。

当这四个条件全部成立时,2SLS仅利用工具变量所生成的外生路由变异,即可提取路由对任务完成影响的因果估计。

前置要求

你需要:

为本教程安装相关包:

pip install numpy pandas statsmodels scipy

这将安装教程中使用的四个软件包。statsmodels 提供OLS和公式API,scipy 用于bootstrap步骤中的统计计算。

克隆伴随仓库以获取合成数据集:

git clone https://github.com/RudrenduPaul/product-experimentation-causal-inference-genai-llm.git
cd product-experimentation-causal-inference-genai-llm
python data/generate_data.py --seed 42 --n-users 50000 --out data/synthetic_llm_logs.csv

你克隆配套仓库,并使用固定种子重新生成共享的 50,000 用户合成数据集,以便你的结果与本文中的预期输出一致。

设置工作示例

本教程在共享数据集的用户协变量之上添加了三个模拟变量,在代码中构建完整的 IV 因果图:

透明度说明:在实际生产分析中,限流回退事件来自你的 API 网关日志。你的用户遥测表不会有这些事件。你需要连接这两个数据源来构建工具变量。

此处的模拟保留了真实工具变量的结构性特征:它因基础设施原因触发,与查询质量无关,且不需要生产网关日志。

import numpy as np
import pandas as pd
import statsmodels.formula.api as smf

np.random.seed(42)

df = pd.read_csv("data/synthetic_llm_logs.csv")
rng = np.random.default_rng(99)
n = len(df)

# Unobserved confounder: complex queries route premium AND complete less often
query_complexity = rng.normal(0, 1, n)

# Endogenous routing: depends on query_confidence (observable)
# and query_complexity (unobserved): this is the confounding structure
log_odds = -2.0 + 4.0 * (1.0 - df["query_confidence"]) + 0.6 * query_complexity
premium_prob = 1.0 / (1.0 + np.exp(-log_odds))
df["routed_to_premium_iv"] = rng.binomial(1, premium_prob).astype(int)

# Instrument: pure Bernoulli(0.15), independent of all query characteristics
df["rate_limit_fallback"] = rng.binomial(1, 0.15, n)

# Actual routing: premium if intended, unless fallback overrides
df["routed_to_premium_actual"] = (
    df["routed_to_premium_iv"] * (1 - df["rate_limit_fallback"])
).astype(int)

# Outcome: known causal structure with +0.06 premium effect
engagement_base = np.where(df.engagement_tier == "heavy", 0.70,
                  np.where(df.engagement_tier == "medium", 0.55, 0.35))
completion_prob = np.clip(
    engagement_base
    + 0.06 * df["routed_to_premium_actual"]  # true causal effect
    - 0.04 * query_complexity                 # unobserved confounder
    + rng.normal(0, 0.02, n),
    0.01, 0.99
)
df["task_completed_iv"] = rng.binomial(1, completion_prob).astype(int)

# Encode engagement tier as dummies
df = pd.get_dummies(df, columns=["engagement_tier"], drop_first=True)
tier_dummies = [c for c in df.columns if c.startswith("engagement_tier_")]
covariate_str = " + ".join(["query_confidence"] + tier_dummies)

print(f"Rate-limit fallback rate:      {df.rate_limit_fallback.mean():.3f}")
print(f"Premium routing rate (actual): {df.routed_to_premium_actual.mean():.3f}")
print(f"Mean confidence | fallback=1:  {df[df.rate_limit_fallback==1].query_confidence.mean():.3f}")
print(f"Mean confidence | fallback=0:  {df[df.rate_limit_fallback==0].query_confidence.mean():.3f}")

预期输出:

Rate-limit fallback rate:      0.151
Premium routing rate (actual): 0.271
Mean confidence | fallback=1:  0.716
Mean confidence | fallback=0:  0.715

在上述代码中,fallback=1 组和 fallback=0 组之间几乎相同的平均置信度分数证实了工具变量与可观察的路由信号无关。这是你可以对任何提议的工具变量进行的独立性假设检验。query_complexity 在此模拟中可用,但在生产环境中无法观测到。回归从未接收到它。

步骤 1:朴素 OLS(有偏基线)

首先运行标准回归,会建立你在不考虑混杂结构时会遇到的有偏基线。大多数工程团队报告这个数字,却并未意识到它在数学上存在缺陷。

ols_formula = f"task_completed_iv ~ routed_to_premium_actual + {covariate_str}"
ols_model = smf.ols(ols_formula, data=df).fit(cov_type="HC3")

ols_coef = ols_model.params["routed_to_premium_actual"]
ols_se   = ols_model.bse["routed_to_premium_actual"]
ols_pval = ols_model.pvalues["routed_to_premium_actual"]
print(f"OLS estimate of premium routing effect: {ols_coef:+.4f}")
print(f"HC3 standard error:                      {ols_se:.4f}")
print(f"p-value:                                 {ols_pval:.4f}")

预期输出:

OLS estimate of premium routing effect: +0.0327
HC3 standard error:                      0.0050
p-value:                                 0.0000

情况是这样的:OLS得到的估计值为+3.3个百分点(概率单位,因为task_completed_iv在线性概率模型中是0/1二元结果)。真实的因果效应为+6.0个百分点。这2.7个百分点的偏差来自未观测到的查询复杂度路由:更难的查询被路由到高级(premium),而它们的完成率较低,这是一种向下的混杂机制。p值看起来显著,标准误看起来精确。这个输出中没有任何信息告诉你这个估计是错误的。

记住这个数字:第2步的2SLS结果将揭示这个差距。

第2步:从头实现两阶段最小二乘法(2SLS)

两阶段最小二乘法通过隔离由速率限制回退(rate-limit fallbacks)产生的外生路由变异,仅使用该变异来估计因果效应,从而纠正偏差。

第1阶段:使用工具变量和协变量预测路由。

stage1_formula = f"routed_to_premium_actual ~ rate_limit_fallback + {covariate_str}"
stage1 = smf.ols(stage1_formula, data=df).fit(cov_type="HC3")

print(f"Stage 1 instrument coefficient: {stage1.params['rate_limit_fallback']:+.4f}")
print(f"p-value:                         {stage1.pvalues['rate_limit_fallback']:.4f}")

df["rtp_hat"] = stage1.fittedvalues

预期输出:

Stage 1 instrument coefficient: -0.3190
p-value:                         0.0000

在这段代码中,你将内生路由变量对工具变量以及将在第二阶段使用的相同观测协变量进行回归。

拟合值rtp_hat包含两个部分:工具变量解释的外生变异,以及协变量解释的外生变异。

内生成分(与未观测到的查询复杂性相关的变异)保留在残差中,并从rtp_hat中剔除。rate_limit_fallback上的负系数证实了相关性假设:当回退机制触发时,高级路由概率大约下降32个百分点。

第二阶段:将结果对预测路由进行回归。

stage2_formula = f"task_completed_iv ~ rtp_hat + {covariate_str}"
stage2 = smf.ols(stage2_formula, data=df).fit(cov_type="HC3")

tsls_coef = stage2.params["rtp_hat"]
tsls_se   = stage2.bse["rtp_hat"]
print(f"2SLS estimate:              {tsls_coef:+.4f}")
print(f"Stage-2 SE (underestimate): {tsls_se:.4f}")

预期输出:

2SLS estimate:              +0.0599
Stage-2 SE (underestimate): 0.0188

情况是这样的:将 routed_to_premium_actual 替换为 rtp_hat 会去除路由变动中的内生部分。第二阶段系数(+0.0599)是优质路由对任务完成率的因果效应的2SLS估计值,几乎正好等于+0.06的真实值。

关于标准误有一个重要的注意事项:手动2SLS产生的第二阶段标准误太小。第二阶段的OLS将 rtp_hat 视为一个固定的、已知的回归元,但事实上它是在第一阶段中从数据估计出来的。这个估计误差增加了一个方差分量,而第二阶段的残差却从未反映出来。

对于你向利益相关者报告的任何结果,请使用 linearmodels.IV2SLS(如"下一步该做什么"所示),它会计算正确的三明治方差。

并排比较OLS和2SLS:

print(f"OLS estimate (biased):  {ols_coef:+.4f}")
print(f"2SLS estimate (IV):     {tsls_coef:+.4f}")
print(f"True premium effect:   +0.0600")
print(f"OLS bias:               {ols_coef - 0.06:+.4f}")

预期输出:

OLS estimate (biased):  +0.0327
2SLS estimate (IV):     +0.0599
True premium effect:   +0.0600
OLS bias:               -0.0273

此处,OLS 低估了真实效应 2.7 个百分点,低估幅度达 45%。2SLS 将其恢复到 0.01 个百分点以内。差距的方向与混杂机制一致:未观测到的查询复杂度将困难查询路由到高级模型并降低其完成率,从而将 OLS 系数向下拉动。

dc39aa79-c955-4c4e-9962-f5a648d6e383

图 2:基于 50,000 用户合成数据集的数据驱动结果。左图:按回退组划分的路由率证实了第一阶段关系:fallback=0 的查询以 39.1% 路由到高级,fallback=1 的查询以 0% 路由(完全覆盖)。右图:OLS 置信区间(红色)完全错过真实的 +0.06 个百分点效应。2SLS 置信区间(绿色)覆盖了它。更宽的 2SLS 区间反映了仅依赖工具变量外生变异的方差成本。

步骤 3:弱工具变量诊断

一种对结果影响很小的有效工具是弱工具。弱工具会产生方差巨大的 2SLS 估计值,在小样本中这些估计值会向 OLS 估计值漂移,从而违背了目的。标准诊断方法是第一阶段 F 统计量。

stage1_restricted = smf.ols(
    f"routed_to_premium_actual ~ {covariate_str}", data=df
).fit()

f_stat, f_pval, _ = stage1.compare_f_test(stage1_restricted)
print(f"First-stage F-statistic (instrument): {f_stat:.2f}")
print(f"p-value:                               {f_pval:.4f}")

if f_stat > 10:
    print("Instrument is STRONG (F > 10). 2SLS estimates are reliable.")
elif f_stat > 4:
    print("Instrument is BORDERLINE WEAK (4 < F < 10). Interpret with caution.")
else:
    print("Instrument is WEAK (F < 4). 2SLS estimates are unreliable.")

print(f"\nFirst-stage coefficient on instrument: "
      f"{stage1.params['rate_limit_fallback']:+.4f}")

预期输出:

First-stage F-statistic (instrument): 3780.94
p-value:                               0.0000
Instrument is STRONG (F > 10). 2SLS estimates are reliable.

First-stage coefficient on instrument: -0.3190

在上面的代码中,你使用F检验将完整的阶段1模型(包含工具变量)与受限模型(不含工具变量)进行比较。F值为3780,远远高于Staiger-Stock经验法则。将15%的后备率应用于50,000个观测值,会产生一个规模较大且估计精确的一阶段效应。

在真实的生产数据集中,如果后备率较低或数据集较小,F统计量将会更低。如果得到的F统计量低于10,请在得出结论之前寻找更强的工具变量或添加更多后备数据。

工具变量强度与排除性限制之间存在权衡,这一点值得明确指出。你可以通过提高后备率来增强工具变量,但如果将其推至足以影响用户体验的水平,后备机制就会通过满意度和重试行为直接作用于任务完成度,从而违反排除性限制。一个既能满足相关性又满足排除性限制的强工具变量才是目标。

内生性方向检验:

gap = ols_coef - tsls_coef
print(f"OLS minus 2SLS gap: {gap:+.4f}")
if abs(gap) > 0.005:
    print("Gap suggests endogeneity bias is present in OLS.")
else:
    print("Small gap: OLS and 2SLS broadly agree.")
print("For a formal Hausman endogeneity test, use linearmodels IV2SLS.")

预期输出:

OLS minus 2SLS gap: -0.0272
Gap suggests endogeneity bias is present in OLS.
For a formal Hausman endogeneity test, use linearmodels IV2SLS.

以下是正在发生的情况:OLS和2SLS之间的差距就是内生性的诊断指标。2.7个百分点的差距证实了路由变量确实与未观测到的混杂因素相关,并且OLS吸收了混杂因素的部分效应。

要进行形式上有效的豪斯曼检验(在原假设下产生具有已知分布的卡方统计量),请使用linearmodels.IV2SLS的内置检验。上述方向检查仅是一种快速诊断。

第4步:LATE是你真正关心的量

2SLS估计的是局部平均处理效应(LATE),也称为依从者平均因果效应(CACE)。LATE仅适用于依从者:即当工具变量触发时,路由实际发生变化的特定查询子集。速率限制回退仅影响经历回退的符合高级资格的查询,因此LATE是针对该子人群的。

compliers_mask = df["rate_limit_fallback"] == 1
complier_count = compliers_mask.sum()
complier_pct   = complier_count / n * 100

print(f"Approximate complier population: {complier_count:,} ({complier_pct:.1f}% of queries)")
print(f"\nComplier mean confidence:     {df[compliers_mask]['query_confidence'].mean():.3f}")
print(f"Non-complier mean confidence: {df[~compliers_mask]['query_confidence'].mean():.3f}")
print(f"\n2SLS LATE estimate: {tsls_coef:+.4f}")
print("This is the causal effect of premium routing for queries rerouted")
print("by rate-limit fallbacks, not all queries in the dataset.")

预期输出:

Approximate complier population: 7,575 (15.2% of queries)

Complier mean confidence:     0.716
Non-complier mean confidence: 0.715

2SLS LATE estimate: +0.0599
This is the causal effect of premium routing for queries rerouted
by rate-limit fallbacks, not all queries in the dataset.

在这段代码中,依从者总体为7,575个查询(这些查询经历了速率限制回退,并从高级路由到廉价)。他们的平均置信度(0.716)与非依从者组(0.715)几乎相同,证实了回退的触发与查询特征无关。

当依从者在可观测变量上看起来是所有查询的一个代表性切片时,LATE通常是平均处理效应(ATE)的合理近似。

可观测代表性满足最低诊断标准。正式的LATE到ATE条件要求要么所有单位的处理效应同质,要么对总体中每个单位都有一个有效的工具变量。如果你的路由效应在查询类型间存在异质性(例如,高级路由对复杂查询的帮助远大于简单查询),那么即使依从者的平均置信度看起来与非依从者组相似,LATE也可能与ATE产生显著差异。

对于战略性容量规划,这正是你需要的指标。当你询问是否投资于更大的高级模型容量或调整速率限制时,你是在问一个关于当前受基础设施约束的查询的具体问题。2SLS直接回答了这个问题。

步骤5:Bootstrap置信区间

手动2SLS产生的第二阶段标准误差过小,如步骤2所述。Bootstrap置信区间为你提供了可靠的不确定性估计,而无需推导正确的解析方差公式。Bootstrap对完整的两阶段过程一起重采样,捕获两个阶段的抽样方差。

rng_boot = np.random.default_rng(7)
ols_boot, tsls_boot = [], []

for _ in range(500):
    samp = df.sample(len(df), replace=True,
                     random_state=int(rng_boot.integers(1_000_000_000)))

    # OLS bootstrap
    ols_b = smf.ols(
        f"task_completed_iv ~ routed_to_premium_actual + {covariate_str}",
        data=samp
    ).fit()
    ols_boot.append(ols_b.params["routed_to_premium_actual"])

    # 2SLS bootstrap (two stages together)
    s1b = smf.ols(
        f"routed_to_premium_actual ~ rate_limit_fallback + {covariate_str}",
        data=samp
    ).fit()
    samp = samp.copy()
    samp["rtp_hat"] = s1b.fittedvalues
    s2b = smf.ols(
        f"task_completed_iv ~ rtp_hat + {covariate_str}",
        data=samp
    ).fit()
    tsls_boot.append(s2b.params["rtp_hat"])

ols_ci  = (np.percentile(ols_boot, 2.5),  np.percentile(ols_boot, 97.5))
tsls_ci = (np.percentile(tsls_boot, 2.5), np.percentile(tsls_boot, 97.5))
true_eff = 0.0600

print(f"OLS  95% CI: [{ols_ci[0]:+.4f}, {ols_ci[1]:+.4f}]")
print(f"2SLS 95% CI: [{tsls_ci[0]:+.4f}, {tsls_ci[1]:+.4f}]")
print(f"Ground truth: +{true_eff:.4f}")
print(f"OLS CI covers ground truth:  {ols_ci[0] <= true_eff <= ols_ci[1]}")
print(f"2SLS CI covers ground truth: {tsls_ci[0] <= true_eff <= tsls_ci[1]}")

预期输出:

OLS  95% CI: [+0.0227, +0.0426]
2SLS 95% CI: [+0.0247, +0.0969]
Ground truth: +0.0600
OLS CI covers ground truth:  False
2SLS CI covers ground truth: True

在这段代码中,OLS的95%置信区间([+0.023, +0.043])完全遗漏了真实的+0.06效应。该区间内的每个值都低于真实值:OLS在自信地犯错。2SLS置信区间([+0.025, +0.097])覆盖了真实值。它比OLS区间更宽,反映了IV估计的方差代价:你以精度换取有效性。

Bootstrap在每次迭代中对两个阶段都进行重抽样,因此不确定性正确反映了二阶段结构。在手动实现的2SLS结果报告中,应使用Bootstrap置信区间,因为它们比第二阶段参数标准误更可靠。

工具变量何时失效

IV分析有其失效模式,比倾向得分或断点回归更加隐蔽,因为四个假设中有两个无法仅从数据中检验。

弱工具变量

第一阶段F统计量低于10表明存在严重的识别问题。弱工具变量会导致2SLS估计量方差增大,并在有限样本中向OLS漂移,重现有偏基线,同时表面上似乎在执行更复杂的方法。在解释任何IV结果之前,请检查F统计量。

如果F低于10,请寻找更强的工具变量,或在报告估计值时附上明确的弱工具变量警告。此处的工具变量很强(F = 3780),因为15%的回退率应用于50,000个查询,产生了7,500多次路由变更。

排他性限制违反

如果限流回退通过路由决策以外的任何渠道影响任务完成,则排他性失效。

存在两种合理的违反情形:回退事件集中在高流量时段,此时用户也更可能正在处理复杂的批处理任务,这使得工具变量最终与查询难度相关。或者,经历回退的用户注意到响应质量下降并放弃会话,通过用户挫败感创建了一条从Z到Y的直接路径。

两者都违反了排他性,同时保持了相关性。你无法从数据中检验它们,必须依据系统知识进行论证。

LATE与ATE的混淆

如果依从者是非典型的,那么使用LATE估计值来论证广泛的路由策略变更就是错误的。如果限流回退不成比例地打击复杂查询(因为复杂查询耗时更长,更可能在会话中途触发限流),那么LATE覆盖的是该复杂查询子群体的高级路由的因果效应。

将其当作ATE来报告会夸大对所有查询进行高级路由的收益。步骤4中的依从者特征表是诊断工具:如果依从者和非依从者在可观测变量上看起来相似,那么LATE就是对ATE的一个可信近似。

违抗者与单调性假设

LATE的解释需要单调性:工具变量使所有受影响单位朝同一方向移动。对于限流回退,这一点几乎可以肯定成立,因为回退总是降低受影响查询被高级路由的概率。

如果存在某种补偿机制(例如,一次回退触发对下一次查询的优先级提升),那么你就遇到了违抗者,单调性假设随之失效。在信任LATE之前,请验证方向一致性。

下一步该做什么

本教程中的手动2SLS实现对该机制是透明的,但产生的标准误不正确。对于你向利益相关者报告或纳入已发表分析的任何结果,请使用linearmodels.IV2SLS

# Production-grade 2SLS with correct standard errors
# pip install linearmodels
from linearmodels.iv import IV2SLS

exog_vars = ["query_confidence"] + tier_dummies
iv_model = IV2SLS.from_formula(
    f"task_completed_iv ~ 1 + {' + '.join(exog_vars)} "
    f"[routed_to_premium_actual ~ rate_limit_fallback]",
    data=df
).fit(cov_type="robust")

print(iv_model.summary)

这里是正在发生的事情:linearmodels 计算了考虑两阶段结构的正确2SLS方差,运行了适当的第一阶段诊断汇总,并提供了正式的豪斯曼内生性检验。语法将内生变量和工具变量括起来:[D ~ Z]

完整实现(包括自助置信区间和图2中的可视化)位于随附笔记本中,见 github.com/RudrenduPaul/product-experimentation-causal-inference-genai-llm/tree/main/11_instrumental_variables/。克隆仓库,生成合成数据集,然后运行 iv_demo.ipynb 以端到端地重现每个代码块。

关于何时使用IV的最后一点说明:如果您的系统支持强制路由随机化(无论置信度得分如何,将一部分查询随机分配给高级路由),那么标准的A/B测试更简单,并能产生全量ATE估计。

当随机化不可行时,IV是合适的工具:当路由规则已固化在生产逻辑中时,当您无法承担故意将查询路由到次优路径的代价时,或者当您需要使用历史观测数据时。如果您能进行真正的实验,那就去做。

对于任何优化路由系统,混杂是结构性常态。标准回归将模型质量和查询的固有难度混入一个系数中,当您需要将它们分开时却同时测量了两者。

速率限制回退提供了干净、自然的工具变量,可以从路由信号中过滤掉基础设施噪声。这种方法为您的团队提供了关于模型架构如何真正驱动业务价值的可靠因果估计。

——

🧑‍💻

zhirenhun

一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。

← 上一篇
为什么尖峰推理流量会破坏专用GPU算力模型
下一篇 →
生产环境中运行Qwen 3:推理供应商对比

📌 相关推荐

GraphRAG 是推理问题,而非数据库问题
2026/8/30
构建市场时光机:使用 Python 和 WebSocket 重放交易会话
2026/8/30
如何自行基准测试LLM推理:值得信赖的数字设计标准
2026/8/30
← 返回文章列表