当您在自动化操作中添加 webhook URL 时,只要您定义的规则匹配到任何新的运行,LangSmith 就会向您的 webhook 端点发送 POST 请求。
Webhook 负载
LangSmith 发送到您 webhook 端点的负载包含:
"rule_id":这是发送此负载的自动化规则的 ID。
"start_time" 和 "end_time":这是 LangSmith 找到匹配运行的时间边界。
"runs":这是一个运行数组,其中每个运行都是一个字典。如果您需要关于每个运行的更多信息,请在您的端点中使用 SDK 从 API 获取。
"feedback_stats":这是一个包含运行反馈统计数据的字典。此字段的示例负载如下代码块所示。
"feedback_stats" : {
" about_langchain " : {
" n " : 1 ,
" avg " : 0.0 ,
" show_feedback_arrow " : true ,
" values " : {}
},
" category " : {
" n " : 0 ,
" avg " : null ,
" show_feedback_arrow " : true ,
" values " : {
" CONCEPTUAL " : 1
}
},
" user_score " : {
" n " : 2 ,
" avg " : 0.0 ,
" show_feedback_arrow " : false ,
" values " : {}
},
" vagueness " : {
" n " : 1 ,
" avg " : 0.0 ,
" show_feedback_arrow " : true ,
" values " : {}
}
}
从 S3 URL 获取数据 根据您的运行的新近程度,inputs_s3_urls 和 outputs_s3_urls 字段可能包含指向实际数据的 S3 URL,而不是数据本身。 inputs 和 outputs 可以通过 inputs_s3_urls 和 outputs_s3_urls 中提供的 ROOT.presigned_url 分别获取。
以下是 LangSmith 发送到您 webhook 端点的完整负载示例:
{
" rule_id " : "d75d7417-0c57-4655-88fe-1db3cda3a47a" ,
" start_time " : "2024-04-05T01:28:54.734491+00:00" ,
" end_time " : "2024-04-05T01:28:56.492563+00:00" ,
" runs " : [
{
" status " : "success" ,
" is_root " : true ,
" trace_id " : "6ab80f10-d79c-4fa2-b441-922ed6feb630" ,
" dotted_order " : "20230505T051324571809Z6ab80f10-d79c-4fa2-b441-922ed6feb630" ,
" run_type " : "tool" ,
" modified_at " : "2024-04-05T01:28:54.145062" ,
" tenant_id " : "2ebda79f-2946-4491-a9ad-d642f49e0815" ,
" end_time " : "2024-04-05T01:28:54.085649" ,
" name " : "Search" ,
" start_time " : "2024-04-05T01:28:54.085646" ,
" id " : "6ab80f10-d79c-4fa2-b441-922ed6feb630" ,
" session_id " : "6a3be6a2-9a8c-4fc8-b4c6-a8983b286cc5" ,
" parent_run_ids " : [],
" child_run_ids " : null ,
" direct_child_run_ids " : null ,
" total_tokens " : 0 ,
" completion_tokens " : 0 ,
" prompt_tokens " : 0 ,
" total_cost " : null ,
" completion_cost " : null ,
" prompt_cost " : null ,
" first_token_time " : null ,
" app_path " : "/o/2ebda79f-2946-4491-a9ad-d642f49e0815/projects/p/6a3be6a2-9a8c-4fc8-b4c6-a8983b286cc5/r/6ab80f10-d79c-4fa2-b441-922ed6feb630?trace_id=6ab80f10-d79c-4fa2-b441-922ed6feb630&start_time=2023-05-05T05:13:24.571809" ,
" in_dataset " : false ,
" last_queued_at " : null ,
" inputs " : null ,
" inputs_s3_urls " : null ,
" outputs " : null ,
" outputs_s3_urls " : null ,
" extra " : null ,
" events " : null ,
" feedback_stats " : null ,
" serialized " : null ,
" share_token " : null
}
]
}
安全性
在 webhook URL 中添加一个秘密查询字符串参数,并在每个传入请求上进行验证。这确保了如果有人发现了您的 webhook URL,您可以将这些调用与真实的 webhook 通知区分开来。
一个示例是
https://api.example.com/langsmith_webhook?secret=38ee77617c3a489ab6e871fbeb2ec87d
Webhook 自定义 HTTP 头
如果您希望随 webhook 发送任何特定的头信息,可以按 URL 进行配置。要设置此项,请单击 URL 字段旁边的 Headers 选项并添加您的头信息。
Webhook 投递
在向您的 webhook 端点投递事件时,LangSmith 遵循以下准则:
如果 LangSmith 无法连接到您的端点,LangSmith 会在宣布投递失败之前重试传输连接最多 2 次。
如果您的端点回复时间超过 5 秒,LangSmith 将宣布投递失败并不再重试。
如果您的端点在 5 秒内返回 5xx 状态码,LangSmith 将使用指数退避策略重试最多 2 次。
如果您的端点返回 4xx 状态码,LangSmith 将宣布投递失败并不再重试。
您端点在响应体中返回的任何内容都将被忽略。
确保评估在 webhook 触发前完成
默认情况下,自动化规则在独立的调度上运行。扫描同一项目的 webhook 规则和在线评估器规则可能在不同时间拾取相同的运行,因此 webhook 可能在评估器有机会对该运行进行评分之前触发。
推荐的解决方案是为您的 webhook 规则添加一个 反馈过滤器 。这告诉 LangSmith 只有在运行已经携带预期分数后才将其发送到您的 webhook,无论它何时被评估。
例如,您有一个在线评估器生成 answer_usefulness 分数,以及一个仅在该分数存在后才应触发的 webhook 规则。
在您的跟踪项目的 自动化 选项卡中打开 webhook 自动化规则。
编辑规则的过滤器以要求反馈键。在过滤器构建器中,添加一个条件:
has(feedback_key, "answer_usefulness")
保存规则。
现在,webhook 规则将跳过任何尚未具有 answer_usefulness 分数的运行。当评估器规则运行并附加分数时,webhook 规则的下一个轮询周期将拾取这些运行并将其发送到您的端点。
您还可以根据分数值本身进行过滤,而不仅仅是其存在性。例如,要仅将具有低有用性分数的运行发送到您的端点: has(feedback_key, "answer_usefulness") and feedback_score < 0.5
有关完整的过滤器语法,请参阅过滤跟踪 。
在单个自动化规则中,操作按固定顺序执行:标注队列 → 数据集 → webhook → 评估。这意味着如果您的 webhook 和评估器配置在同一 规则上,webhook 将始终在该规则的运行完成评估之前触发。为确保 webhook 接收评估分数,请将 webhook 和评估器保持为单独的规则 ,并在 webhook 规则上使用反馈过滤器,如示例中所述。
使用 Modal 的示例
本指南使用 Modal 来展示如何设置此功能。Modal 提供用于推理和微调的自动扩展 GPU、用于代码代理的安全容器化以及无服务器 Python Web 端点。本指南重点介绍 Web 端点。
首先,创建一个 Modal 帐户。然后,在本地安装 Modal SDK:
要完成帐户设置,请运行以下命令:
按照说明完成帐户设置。
接下来,您需要在 Modal 中设置一些密钥。
首先,LangSmith 需要通过传递密钥来向 Modal 进行身份验证。
最简单的方法是在查询参数中传递密钥。
要验证此密钥,请在 Modal 中添加一个密钥进行验证。
通过创建 Modal 密钥 来完成此操作。
将密钥命名为 ls-webhook 并设置一个名为 LS_WEBHOOK 的环境变量。
您还可以设置一个 LangSmith 密钥——幸运的是,已经有一个集成模板可以用于此!
之后,您可以创建一个 Python 文件作为您的端点。
以下代码块中显示了一个示例,其中的注释解释了正在发生的事情:
from fastapi import HTTPException , status , Request , Query
from modal import Secret , Stub , web_endpoint , Image
stub = Stub ( "auth-example" , image = Image . debian_slim (). pip_install ( "langsmith" ))
@stub . function (
secrets = [ Secret . from_name ( "ls-webhook" ), Secret . from_name ( "my-langsmith-secret" )]
)
# 我们希望这是一个 `POST` 端点,因为我们将在此处发布数据
@web_endpoint ( method = "POST" )
# 我们设置了一个 `secret` 查询参数
def f ( data : dict , secret : str = Query ( ... )):
# 您可以在 Modal 函数内部导入本地没有的依赖项
from langsmith import Client
# 首先,我们验证传递的密钥
import os
if secret != os . environ [ " LS_WEBHOOK " ]:
raise HTTPException (
status_code = status . HTTP_401_UNAUTHORIZED ,
detail = "Incorrect bearer token" ,
headers = { "WWW-Authenticate" : "Bearer" },
)
# 这是我们放置此 webhook 内部应发生什么逻辑的地方
ls_client = Client ()
runs = data [ " runs " ]
ids = [ r [ " id " ] for r in runs ]
feedback = list ( ls_client . list_feedback ( run_ids = ids ))
for r , f in zip ( runs , feedback ):
try :
ls_client . create_example (
inputs = r [ " inputs " ],
outputs = { "output" : f . correction },
dataset_name = "classifier-github-issues" ,
)
except Exception :
raise ValueError ( f " { r } and { f } " )
# 函数体
return "success!"
使用 modal deploy ... 部署此文件(参见管理 Modal 部署 )。
您现在应该会得到类似以下内容:
✓ Created objects.
├── 🔨 Created mount /Users/harrisonchase/workplace/langsmith-docs/example-webhook.py
├── 🔨 Created mount PythonPackage:langsmith
└── 🔨 Created f => https://hwchase17--auth-example-f.modal.run
✓ App deployed! 🎉
View Deployment: https://modal.com/apps/hwchase17/auth-example
注意函数 URL:https://hwchase17--auth-example-f.modal.run。
注意:这不是最终的部署 URL,请确保不要意外使用它。
连接起来
获取您之前创建的函数 URL 并将其添加为 webhook。
记得同时将密钥作为查询参数传递。
将所有内容放在一起,它应该看起来像:
https://hwchase17--auth-example-f-dev.modal.run?secret={SECRET}
将 {SECRET} 替换为您创建的用于访问 Modal 服务的密钥。
将这些文档连接 到 Claude、VSCode 等,通过 MCP 获取实时答案。