主题
如果您希望导出大量追踪,我们建议您使用批量数据导出功能,因为它可以更好地处理大数据量,并支持跨分区的自动重试和并行化。
查询运行(LangSmith 追踪中的 span 数据)的推荐方式是使用 SDK 中的 list_runs 方法或 API 中的 /runs/query 端点。
LangSmith 以 运行 (span) 数据格式 中指定的简单格式存储追踪。
使用过滤参数
对于简单的查询,您不必依赖我们的查询语法。您可以使用 过滤参数参考 中指定的过滤参数。
前提条件
在运行以下代码片段之前,请先初始化客户端。
python
from langsmith import Client
client = Client()typescript
import { Client, Run } from "langsmith";
const client = new Client();以下是一些使用关键字参数列出运行的方式示例:
列出项目中的所有运行
python
project_runs = client.list_runs(project_name="<your_project>")typescript
// 下载项目中的运行
const projectRuns: Run[] = [];
for await (const run of client.listRuns({
projectName: "<your_project>",
})) {
projectRuns.push(run);
};列出过去 24 小时内的 LLM 和 chat 运行
python
todays_llm_runs = client.list_runs(
project_name="<your_project>",
start_time=datetime.now() - timedelta(days=1),
run_type="llm",
)typescript
const todaysLlmRuns: Run[] = [];
for await (const run of client.listRuns({
projectName: "<your_project>",
startTime: new Date(Date.now() - 1000 * 60 * 60 * 24),
runType: "llm",
})) {
todaysLlmRuns.push(run);
};列出项目中的根运行
根运行是没有父项的运行。这些运行的 is_root 值被分配为 True。您可以使用它来过滤根运行。
python
root_runs = client.list_runs(
project_name="<your_project>",
is_root=True
)typescript
const rootRuns: Run[] = [];
for await (const run of client.listRuns({
projectName: "<your_project>",
isRoot: 1,
})) {
rootRuns.push(run);
};列出没有错误的运行
python
correct_runs = client.list_runs(project_name="<your_project>", error=False)typescript
const correctRuns: Run[] = [];
for await (const run of client.listRuns({
projectName: "<your_project>",
error: false,
})) {
correctRuns.push(run);
};按运行 ID 列出运行
忽略其他参数
如果您按上述方式提供运行 ID 列表,它将忽略所有其他过滤参数,如 project_name、run_type 等,并直接返回与给定 ID 匹配的运行。
如果您有一个运行 ID 列表,可以直接列出它们:
python
run_ids = ['a36092d2-4ad5-4fb4-9c0d-0dba9a2ed836','9398e6be-964f-4aa4-8ae9-ad78cd4b7074']
selected_runs = client.list_runs(id=run_ids)typescript
const runIds = [
"a36092d2-4ad5-4fb4-9c0d-0dba9a2ed836",
"9398e6be-964f-4aa4-8ae9-ad78cd4b7074",
];
const selectedRuns: Run[] = [];
for await (const run of client.listRuns({
id: runIds,
})) {
selectedRuns.push(run);
};按 ID 获取单个运行
要按 ID 获取单个运行(追踪),请使用 read_run 方法。当您有一个特定的追踪 ID(例如,来自 LangSmith 共享链接,如 https://smith.langchain.com/public/<trace-id>/r)并希望检索其完整数据时,这非常有用。
python
run_id = "a36092d2-4ad5-4fb4-9c0d-0dba9a2ed836"
run = client.read_run(run_id)
# 访问运行数据
print(run.inputs)
print(run.outputs)
print(run.name)typescript
const runId = "a36092d2-4ad5-4fb4-9c0d-0dba9a2ed836";
const run = await client.readRun(runId);
// 访问运行数据
console.log(run.inputs);
console.log(run.outputs);
console.log(run.name);使用 LangGraph 在本地重放追踪
如果您在使用带检查点的 LangGraph,可以从 LangSmith 获取追踪并在本地重放以进行调试。有关从检查点恢复执行的详细信息,请参阅 LangGraph 的时间旅行和重放文档。
使用过滤查询语言
对于更复杂的查询,您可以使用 过滤查询语言参考 中描述的查询语言。
列出所有名为 "extractor" 且其追踪根运行被分配了反馈 "user_score" 分数为 1 的运行
python
client.list_runs(
project_name="<your_project>",
filter='eq(name, "extractor")',
trace_filter='and(eq(feedback_key, "user_score"), eq(feedback_score, 1))'
)typescript
client.listRuns({
projectName: "<your_project>",
filter: 'eq(name, "extractor")',
traceFilter: 'and(eq(feedback_key, "user_score"), eq(feedback_score, 1))'
})列出 "star_rating" 键且分数大于 4 的运行
python
client.list_runs(
project_name="<your_project>",
filter='and(eq(feedback_key, "star_rating"), gt(feedback_score, 4))'
)typescript
client.listRuns({
projectName: "<your_project>",
filter: 'and(eq(feedback_key, "star_rating"), gt(feedback_score, 4))'
})列出完成时间超过 5 秒的运行
python
client.list_runs(project_name="<your_project>", filter='gt(latency, "5s")')typescript
client.listRuns({projectName: "<your_project>", filter: 'gt(latency, "5s")'})列出所有 "error" 不等于 null 的运行
python
client.list_runs(project_name="<your_project>", filter='neq(error, null)')typescript
client.listRuns({projectName: "<your_project>", filter: 'neq(error, null)'})列出所有 start_time 大于特定时间戳的运行
python
client.list_runs(project_name="<your_project>", filter='gt(start_time, "2023-07-15T12:34:56Z")')typescript
client.listRuns({projectName: "<your_project>", filter: 'gt(start_time, "2023-07-15T12:34:56Z")'})列出所有包含字符串 "substring" 的运行
python
client.list_runs(project_name="<your_project>", filter='search("substring")')typescript
client.listRuns({projectName: "<your_project>", filter: 'search("substring")'})列出所有标记有 git 哈希 "2aa1cf4" 的运行
python
client.list_runs(project_name="<your_project>", filter='has(tags, "2aa1cf4")')typescript
client.listRuns({projectName: "<your_project>", filter: 'has(tags, "2aa1cf4")'})列出所有在特定时间戳之后开始且 "error" 不等于 null 或 "Correctness" 反馈分数等于 0 的运行
python
client.list_runs(
project_name="<your_project>",
filter='and(gt(start_time, "2023-07-15T12:34:56Z"), or(neq(error, null), and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))'
)typescript
client.listRuns({
projectName: "<your_project>",
filter: 'and(gt(start_time, "2023-07-15T12:34:56Z"), or(neq(error, null), and(eq(feedback_key, "Correctness"), eq(feedback_score, 0.0))))'
})复杂查询:列出所有标签包含 "experimental" 或 "beta" 且延迟大于 2 秒的运行
python
client.list_runs(
project_name="<your_project>",
filter='and(or(has(tags, "experimental"), has(tags, "beta")), gt(latency, 2))'
)typescript
client.listRuns({
projectName: "<your_project>",
filter: 'and(or(has(tags, "experimental"), has(tags, "beta")), gt(latency, 2))'
})按全文搜索追踪树
您可以不带任何特定字段使用 search() 函数,对运行中的所有字符串字段进行全文搜索。这允许您快速找到与搜索词匹配的追踪。
python
client.list_runs(
project_name="<your_project>",
filter='search("image classification")'
)typescript
client.listRuns({
projectName: "<your_project>",
filter: 'search("image classification")'
})检查元数据是否存在
如果您想检查元数据是否存在,可以使用 eq 运算符,可选地结合 and 语句按值匹配。如果您想记录有关运行的更结构化的信息,这非常有用。
python
to_search = {
"user_id": ""
}
# 检查是否存在具有 "user_id" 元数据键的任何运行
client.list_runs(
project_name="default",
filter="eq(metadata_key, 'user_id')"
)
# 检查具有 user_id=4070f233-f61e-44eb-bff1-da3c163895a3 的运行
client.list_runs(
project_name="default",
filter="and(eq(metadata_key, 'user_id'), eq(metadata_value, '4070f233-f61e-44eb-bff1-da3c163895a3'))"
)typescript
// 检查是否存在具有 "user_id" 元数据键的任何运行
client.listRuns({
projectName: 'default',
filter: `eq(metadata_key, 'user_id')`
});
// 检查具有 user_id=4070f233-f61e-44eb-bff1-da3c163895a3 的运行
client.listRuns({
projectName: 'default',
filter: `and(eq(metadata_key, 'user_id'), eq(metadata_value, '4070f233-f61e-44eb-bff1-da3c163895a3'))`
});检查元数据中的环境详细信息
一种常见的模式是通过元数据向追踪添加环境信息。如果您想过滤包含环境元数据的运行,可以使用与上述相同的模式:
python
client.list_runs(
project_name="default",
filter="and(eq(metadata_key, 'environment'), eq(metadata_value, 'production'))"
)typescript
client.listRuns({
projectName: 'default',
filter: `and(eq(metadata_key, 'environment'), eq(metadata_value, 'production'))`
});检查元数据中的对话 ID
关联同一对话中追踪的另一种常见方式是使用共享的对话 ID。如果您想以此种方式基于对话 ID 过滤运行,可以在元数据中搜索该 ID。
python
client.list_runs(
project_name="default",
filter="and(eq(metadata_key, 'conversation_id'), eq(metadata_value, 'a1b2c3d4-e5f6-7890'))"
)typescript
client.listRuns({
projectName: 'default',
filter: `and(eq(metadata_key, 'conversation_id'), eq(metadata_value, 'a1b2c3d4-e5f6-7890'))`
});对键值对进行否定过滤
您可以对元数据、输入和输出键值对使用否定过滤,以从结果中排除特定运行。以下是元数据键值对的一些示例,但同样的逻辑也适用于输入和输出键值对。
python
# 查找元数据中不包含 "conversation_id" 键的所有运行
client.list_runs(
project_name="default",
filter="and(neq(metadata_key, 'conversation_id'))"
)
# 查找元数据中 conversation_id 不为 "a1b2c3d4-e5f6-7890" 的所有运行
client.list_runs(
project_name="default",
filter="and(eq(metadata_key, 'conversation_id'), neq(metadata_value, 'a1b2c3d4-e5f6-7890'))"
)
# 查找没有 "conversation_id" 元数据键且不存在 "a1b2c3d4-e5f6-7890" 值的所有运行
client.list_runs(
project_name="default",
filter="and(neq(metadata_key, 'conversation_id'), neq(metadata_value, 'a1b2c3d4-e5f6-7890'))"
)
# 查找不存在 conversation_id 元数据键但存在 "a1b2c3d4-e5f6-7890" 值的所有运行
client.list_runs(
project_name="default",
filter="and(neq(metadata_key, 'conversation_id'), eq(metadata_value, 'a1b2c3d4-e5f6-7890'))"
)typescript
// 查找元数据中不包含 "conversation_id" 键的所有运行
client.listRuns({
projectName: 'default',
filter: `and(neq(metadata_key, 'conversation_id'))`
});
// 查找元数据中 conversation_id 不为 "a1b2c3d4-e5f6-7890" 的所有运行
client.listRuns({
projectName: 'default',
filter: `and(eq(metadata_key, 'conversation_id'), neq(metadata_value, 'a1b2c3d4-e5f6-7890'))`
});
// 查找没有 "conversation_id" 元数据键且不存在 "a1b2c3d4-e5f6-7890" 值的所有运行
client.listRuns({
projectName: 'default',
filter: `and(neq(metadata_key, 'conversation_id'), neq(metadata_value, 'a1b2c3d4-e5f6-7890'))`
});
// 查找不存在 conversation_id 元数据键但存在 "a1b2c3d4-e5f6-7890" 值的所有运行
client.listRuns({
projectName: 'default',
filter: `and(neq(metadata_key, 'conversation_id'), eq(metadata_value, 'a1b2c3d4-e5f6-7890'))`
});组合多个过滤器
如果您想组合多个条件以细化搜索,可以将 and 运算符与其他过滤函数结合使用。以下是搜索名为 "ChatOpenAI" 且其元数据中还具有特定 conversation_id 的运行的方法:
python
client.list_runs(
project_name="default",
filter="and(eq(name, 'ChatOpenAI'), eq(metadata_key, 'conversation_id'), eq(metadata_value, '69b12c91-b1e2-46ce-91de-794c077e8151'))"
)typescript
client.listRuns({
projectName: 'default',
filter: `and(eq(name, 'ChatOpenAI'), eq(metadata_key, 'conversation_id'), eq(metadata_value, '69b12c91-b1e2-46ce-91de-794c077e8151'))`
});树过滤器 (Tree filter)
列出所有名为 "RetrieveDocs" 的运行,其根运行具有 1 的 "user_score" 反馈,并且完整追踪中的任何运行名为 "ExpandQuery"。
如果您想根据追踪内达到的各种状态或步骤有条件地提取特定运行,此类查询非常有用。
python
client.list_runs(
project_name="<your_project>",
filter='eq(name, "RetrieveDocs")',
trace_filter='and(eq(feedback_key, "user_score"), eq(feedback_score, 1))',
tree_filter='eq(name, "ExpandQuery")'
)typescript
client.listRuns({
projectName: "<your_project>",
filter: 'eq(name, "RetrieveDocs")',
traceFilter: 'and(eq(feedback_key, "user_score"), eq(feedback_score, 1))',
treeFilter: 'eq(name, "ExpandQuery")'
})