背景
我们于 2026 年 5 月发布了 SmithDB,这是一款专为现代 AI 智能体构建的新型可观测性数据库。SmithDB 在所有关键的可观测性工作负载上均提供了行业领先的性能,使 LangSmith 的核心体验速度大幅提升。 查询您的跟踪记录需要使用新的 SDK 方法。本指南将帮助您完成代码库的迁移。废弃与移除时间表
每个 SDK 方法及其底层端点共享相同的废弃日期。| 部署方式 | 废弃时间 | 移除时间 |
|---|---|---|
| 所有云端区域 | 2026 年 7 月底 | 2027 年 1 月 31 日 |
| 自托管 | v0.16 | v0.18 |
最低 SDK 版本要求
新的 SDK 方法从以下 SDK 版本开始可用:| 语言 | 包名 | 最低版本 |
|---|---|---|
| Python | langsmith | >=0.10.8 |
| TypeScript | langsmith | >=0.8.5 |
| Java | langsmith-java | 0.1.0-beta.18 |
| Go | langsmith-go | v0.22.0 |
关于自托管部署
- 本指南中记录的新方法需要
>=0.16的自托管版本,与所使用的数据存储无关。 - ClickHouse 被禁用后,已废弃的方法将停止工作。
- 在可能的情况下,SDK 会发出警告或错误,指明需要升级到的版本,而不是毫无解释地失败。
使用 AI 智能体进行迁移
本指南旨在被 AI 编程智能体直接获取和应用。将以下提示复制到您的智能体中,以将您的代码库迁移到基于 SmithDB 的方法。Migrate this codebase's LangSmith SDK usage to the new SmithDB-backed methods.
Fetch https://docs.langchain.com/langsmith/smithdb-sdk-migration.md and treat it
as the source of truth for what changed, including which methods and
parameters are affected, what replaces them, and deployment support.
1. Check the installed LangSmith SDK version against the minimum version
required for the SmithDB-backed methods per the guide, and upgrade the
dependency if it does not meet that minimum.
2. Identify every call site in this codebase that uses a method the guide
marks as migrated, in whichever language(s) this codebase uses.
3. For each call site, apply the corresponding before/after change from the
guide, including any added, removed, or renamed parameters.
If a call site or parameter is not covered by the guide, stop and ask rather
than guessing.
运行记录:查询
查询项目中的运行记录,支持可选的过滤和字段投影。返回分页的结果集。主要更改
方法名
- Python
- TypeScript
- Java
- Go
- cURL
| 之前 | 之后 |
|---|---|
client.list_runs() | client.runs.query() |
client.runs.query() 现在是异步的。调用时请使用 await。| 之前 | 之后 |
|---|---|
client.listRuns() | client.runs.query() |
| 之前 | 之后 |
|---|---|
client.runs().query() | client.runs().queryV2() |
| 之前 | 之后 |
|---|---|
client.Runs.Query() | client.Runs.QueryV2() |
| 之前 | 之后 |
|---|---|
POST /api/v1/runs/query | POST /api/v2/runs/query |
查询参数
- Python
- TypeScript
- Java
- Go
- cURL
runs.query 不支持 project_name。请改为传递项目 UUID 作为 project_ids。要通过名称查找 UUID,请使用 client.read_project(project_name="my-project"),或在异步代码中使用 await client.aread_project(project_name="my-project")。省略
min_start_time 时,默认值为1天前。之前不带 start_time 的 list_runs 会返回所有历史运行记录;现在不带 min_start_time 的 runs.query 会静默地将查询范围限定在最近24小时内。如果需要更宽的时间范围,请传递显式的 min_start_time。之前 (list_runs) | 之后 (runs.query) | 说明 |
|---|---|---|
project_name | (已移除) | 请使用带 UUID 的 project_ids——见上方警告 |
project_id | project_ids | 现在接受列表;与 reference_dataset_id 互斥 |
run_type | run_type | 值现在必须大写:"LLM"、"CHAIN"、"TOOL"、"RETRIEVER"、"EMBEDDING"、"PROMPT"、"PARSER" |
trace_id | trace_id | 未更改 |
reference_example_id | reference_examples | 现在接受 UUID 列表 |
query | (已移除) | 无对应项 |
filter | filter | 语法未更改 |
trace_filter | trace_filter | 未更改 |
tree_filter | tree_filter | 未更改 |
is_root | is_root | 未更改 |
parent_run_id | (已移除) | 无对应项 |
start_time | min_start_time | 已重命名;默认值为1天前——见上方警告 |
error | has_error | 已重命名 |
run_ids | ids | 已重命名 |
select | selects | 字段名现在大写("NAME"、"STATUS" 等) |
limit | (已移除) | 请使用 page_size 作为每批次大小 |
| (之前不可用) | max_start_time | start_time 的上限;默认为当前时间 |
| (之前不可用) | page_size | 每次请求返回的结果数量(默认 100,最大 1000) |
| (之前不可用) | reference_dataset_id | 作为 project_ids 的替代选项;两者互斥 |
| (之前不可用) | cursor | 传递上次响应中的 next_cursor 以获取下一页 |
client.runs.query 不支持 projectName。请改为传递项目 UUID 作为 project_ids。要通过名称查找 UUID,请使用 client.readProject({ projectName: "my-project" })。省略
min_start_time 时,默认值为1天前。之前不带 startTime 的 listRuns 会返回所有历史运行记录;现在不带 min_start_time 的 client.runs.query 会静默地将查询范围限定在最近24小时内。如果需要更宽的时间范围,请传递显式的 min_start_time。之前 (listRuns) | 之后 (client.runs.query) | 说明 |
|---|---|---|
projectName | (已移除) | 请使用带 UUID 的 project_ids——见上方警告 |
projectId | project_ids | 重命名为 snake_case;现在接受列表;与 reference_dataset_id 互斥 |
runType | run_type | 重命名为 snake_case;值现在必须大写:"LLM"、"CHAIN"、"TOOL"、"RETRIEVER"、"EMBEDDING"、"PROMPT"、"PARSER" |
traceId | trace_id | 重命名为 snake_case |
referenceExampleId | reference_examples | 重命名为 snake_case;现在接受 UUID 列表 |
query | (已移除) | 无对应项 |
filter | filter | 语法未更改 |
traceFilter | trace_filter | 重命名为 snake_case |
treeFilter | tree_filter | 重命名为 snake_case |
isRoot | is_root | 重命名为 snake_case |
parentRunId | (已移除) | 无对应项 |
startTime | min_start_time | 重命名为 snake_case;默认值为1天前——见上方警告 |
error | has_error | 已重命名 |
id | ids | 已重命名 |
select | selects | 字段名现在大写("NAME"、"STATUS" 等) |
limit | (已移除) | 请使用 page_size 作为每批次大小 |
order | (已移除) | 无对应项 |
executionOrder | (已移除) | 无对应项 |
| (之前不可用) | max_start_time | start_time 的上限;默认为当前时间 |
| (之前不可用) | page_size | 每次请求返回的结果数量(默认 100,最大 1000) |
| (之前不可用) | reference_dataset_id | 作为 project_ids 的替代选项;两者互斥 |
| (之前不可用) | cursor | 传递上次响应中的 next_cursor 以获取下一页 |
省略
minStartTime() 时,默认值为1天前。之前不带 startTime() 的 query() 会返回所有历史运行记录;现在不带 minStartTime() 的 queryV2() 会静默地将查询范围限定在最近24小时内。如果需要更宽的时间范围,请传递显式的 minStartTime()。之前 (RunQueryParams) | 之后 (RunQueryV2Params) | 说明 |
|---|---|---|
session() | projectIds() | 已重命名;现在接受显式的项目 UUID |
runType() | runType() | 值现在必须大写 |
trace() | traceId() | 已重命名 |
referenceExample() | referenceExamples() | 已重命名为复数 |
query() | (已移除) | 无对应项 |
filter() | filter() | 语法未更改 |
traceFilter() | traceFilter() | 未更改 |
treeFilter() | treeFilter() | 未更改 |
isRoot() | isRoot() | 未更改 |
parentRun() | (已移除) | 无对应项 |
startTime() | minStartTime() | 已重命名;默认值为1天前——见上方警告 |
error() | hasError() | 已重命名 |
id() | ids() | 已重命名 |
select() | selects() | 字段名现在大写 |
limit() | (已移除) | 请使用 pageSize() |
order() | (已移除) | 无对应项 |
executionOrder() | (已移除) | 无对应项 |
cursor() | cursor() | 未更改 |
| (之前不可用) | maxStartTime() | 开始时间的上限;默认为当前时间 |
| (之前不可用) | pageSize() | 每次请求返回的结果数量(默认 100,最大 1000) |
| (之前不可用) | referenceDatasetId() | 作为 projectIds() 的替代选项 |
省略
MinStartTime 时,默认值为1天前。之前不带 StartTime 的 Query() 会返回所有历史运行记录;现在不带 MinStartTime 的 QueryV2() 会静默地将查询范围限定在最近24小时内。如果需要更宽的时间范围,请传递显式的 MinStartTime。之前 (RunQueryParams) | 之后 (RunQueryV2Params) | 说明 |
|---|---|---|
Session | ProjectIDs | 已重命名;现在接受显式的项目 UUID |
RunType | RunType | 值现在必须大写:RunQueryV2ParamsRunTypeLLM、RunQueryV2ParamsRunTypeChain 等 |
Trace | TraceID | 已重命名 |
ReferenceExample | ReferenceExamples | 已重命名为复数 |
Query | (已移除) | 无对应项 |
Filter | Filter | 未更改 |
TraceFilter | TraceFilter | 未更改 |
TreeFilter | TreeFilter | 未更改 |
IsRoot | IsRoot | 未更改 |
ParentRun | (已移除) | 无对应项 |
StartTime | MinStartTime | 已重命名;默认值为1天前——见上方警告 |
Error | HasError | 已重命名 |
ID | IDs | 已重命名 |
Select | Selects | 字段名常量现在大写(例如 RunQueryV2ParamsSelectName) |
Limit | (已移除) | 请使用 PageSize |
Order | (已移除) | 无对应项 |
ExecutionOrder | (已移除) | 无对应项 |
Cursor | Cursor | 未更改 |
| (之前不可用) | MaxStartTime | 开始时间的上限;默认为当前时间 |
| (之前不可用) | PageSize | 每次请求返回的结果数量(默认 100,最大 1000) |
| (之前不可用) | ReferenceDatasetID | 作为 ProjectIDs 的替代选项 |
省略
min_start_time 时,默认值为1天前。之前不带 start_time 的 POST /api/v1/runs/query 会返回所有历史运行记录;现在不带 min_start_time 的 POST /api/v2/runs/query 会静默地将查询范围限定在最近24小时内。如果需要更宽的时间范围,请传递显式的 min_start_time。之前 (v1 POST /api/v1/runs/query 请求体字段) | 之后 (v2 POST /api/v2/runs/query 请求体字段) | 说明 |
|---|---|---|
session | project_ids | 已重命名;两者都接受项目 UUID 数组。project_ids 与 reference_dataset_id 互斥 |
run_type | run_type | 值现在必须大写:"LLM"、"CHAIN"、"TOOL"、"RETRIEVER"、"EMBEDDING"、"PROMPT"、"PARSER" |
trace | trace_id | 已重命名 |
reference_example | reference_examples | 已重命名为复数;现在接受 UUID 数组 |
query | (已移除) | 无对应项 |
filter | filter | 语法未更改 |
trace_filter | trace_filter | 未更改 |
tree_filter | tree_filter | 未更改 |
is_root | is_root | 未更改 |
parent_run | (已移除) | 无对应项 |
start_time | min_start_time | 已重命名;默认值为1天前——见上方警告 |
error | has_error | 已重命名 |
id | ids | 已重命名为复数 |
select | selects | 字段名现在大写("NAME"、"STATUS" 等) |
limit | (已移除) | 请使用 page_size 作为每批次大小 |
| (之前不可用) | max_start_time | start_time 的上限;默认为当前时间 |
| (之前不可用) | page_size | 每次请求返回的结果数量(默认 100,最大 1000) |
| (之前不可用) | reference_dataset_id | 作为 project_ids 的替代选项;两者互斥 |
| (之前不可用) | cursor | 传递上次响应中的 next_cursor 以获取下一页 |
响应字段
- Python
- TypeScript
- Java
- Go
- cURL
向
selects 传递 SCREAMING_SNAKE_CASE 字符串(例如 "ID"、"NAME"、"STATUS")以控制每个 Run 上填充哪些字段;只有被选中的字段才不是 None。默认的 selects 仅包含 "ID"。之前 (v1 Run 属性) | 之后 (v2 Run 属性) | 说明 |
|---|---|---|
run.id | run.id | 未更改;省略 selects 时默认返回 |
run.name | run.name | 未更改 |
run.run_type | run.run_type | 值现在是字面量大写形式:"LLM"、"CHAIN" 等 |
run.status | run.status | 值:"SUCCESS"、"ERROR"、"PENDING" |
run.start_time | run.start_time | 未更改 |
run.end_time | run.end_time | 未更改 |
run.error | run.error | 未更改 |
run.inputs | run.inputs | 未更改 |
run.outputs | run.outputs | 未更改 |
run.tags | run.tags | 未更改 |
run.extra | run.extra | 未更改 |
run.metadata | run.metadata | 未更改 |
run.events | run.events | 未更改 |
run.reference_example_id | run.reference_example_id | 未更改 |
run.trace_id | run.trace_id | 未更改 |
run.dotted_order | run.dotted_order | 未更改 |
run.parent_run_id | (已移除) | 请使用 run.parent_run_ids(所有祖先 UUID 的列表,根在先) |
run.parent_run_ids | run.parent_run_ids | 未更改 |
run.session_id | run.project_id | 已重命名;session_id 是项目 UUID |
run.feedback_stats | run.feedback_stats | 未更改 |
run.app_path | run.app_path | 未更改 |
run.attachments | run.attachments | v2 返回预签名的下载 URL 而不是原始字节 |
run.total_tokens | run.total_tokens | 未更改 |
run.prompt_tokens | run.prompt_tokens | 未更改 |
run.completion_tokens | run.completion_tokens | 未更改 |
run.total_cost | run.total_cost | 未更改 |
run.prompt_cost | run.prompt_cost | 未更改 |
run.completion_cost | run.completion_cost | 未更改 |
run.first_token_time | run.first_token_time | 未更改 |
run.latency (属性) | run.latency_seconds | 已重命名;曾是计算属性 timedelta,现在是原生 float 字段 |
run.in_dataset | run.is_in_dataset | 已重命名 |
run.child_run_ids | (已移除) | 无对应项 |
run.child_runs | (已移除) | 无对应项 |
run.serialized | (已移除) | 请使用 run.manifest |
run.manifest_id | (已移除) | 请使用 run.manifest |
| (之前不可用) | run.is_root | 新增 |
| (之前不可用) | run.manifest | 新增:完整的清单对象(替代 serialized 和 manifest_id) |
| (之前不可用) | run.error_preview | 新增:截断的错误片段 |
| (之前不可用) | run.inputs_preview | 新增:截断的输入预览 |
| (之前不可用) | run.outputs_preview | 新增:截断的输出预览 |
| (之前不可用) | run.thread_id | 新增:对话线程 UUID |
| (之前不可用) | run.reference_dataset_id | 新增:参考示例的数据集 UUID |
| (之前不可用) | run.share_url | 新增:公共分享 URL(仅当运行记录被分享时设置) |
run.prompt_token_details | run.prompt_token_details.raw | 字段现在包装了该字典;访问 .raw 以获取 dict[str, int](元素类型未更改) |
run.completion_token_details | run.completion_token_details.raw | 字段现在包装了该字典;访问 .raw 以获取 dict[str, int](元素类型未更改) |
run.prompt_cost_details | run.prompt_cost_details.raw | 字段现在包装了该字典;访问 .raw 以获取 dict[str, float](曾是 dict[str, Decimal]) |
run.completion_cost_details | run.completion_cost_details.raw | 字段现在包装了该字典;访问 .raw 以获取 dict[str, float](曾是 dict[str, Decimal]) |
向
selects 传递 SCREAMING_SNAKE_CASE 字符串(例如 "ID"、"NAME"、"STATUS")以控制每个 Run 上填充哪些字段。默认的 selects 仅包含 "ID"。之前 (v1 Run 属性) | 之后 (v2 Run 属性) | 说明 |
|---|---|---|
run.id | run.id | 未更改 |
run.name | run.name | 未更改 |
run.runType | run.run_type | 重命名为 snake_case;值现在大写:"LLM"、"CHAIN" 等 |
run.status | run.status | 值:"SUCCESS"、"ERROR"、"PENDING" |
run.startTime | run.start_time | 重命名为 snake_case |
run.endTime | run.end_time | 重命名为 snake_case |
run.error | run.error | 未更改 |
run.inputs | run.inputs | 未更改 |
run.outputs | run.outputs | 未更改 |
run.tags | run.tags | 未更改 |
run.extra | run.extra | 未更改 |
| (之前不可用) | run.metadata | 新增:之前通过 run.extra.metadata 访问 |
run.events | run.events | 未更改 |
run.referenceExampleId | run.reference_example_id | 重命名为 snake_case |
run.traceId | run.trace_id | 重命名为 snake_case |
run.dottedOrder | run.dotted_order | 重命名为 snake_case |
run.parentRunId | (已移除) | 请使用 run.parent_run_ids(所有祖先 UUID 的列表,根在先) |
run.parentRunIds | run.parent_run_ids | 重命名为 snake_case |
run.sessionId | run.project_id | 已重命名;sessionId 是项目 UUID |
run.feedbackStats | run.feedback_stats | 重命名为 snake_case |
run.appPath | run.app_path | 重命名为 snake_case |
run.attachments | run.attachments | v2 返回预签名的下载 URL 而不是原始字节 |
run.totalTokens | run.total_tokens | 重命名为 snake_case |
run.promptTokens | run.prompt_tokens | 重命名为 snake_case |
run.completionTokens | run.completion_tokens | 重命名为 snake_case |
run.totalCost | run.total_cost | 重命名为 snake_case |
run.promptCost | run.prompt_cost | 重命名为 snake_case |
run.completionCost | run.completion_cost | 重命名为 snake_case |
run.firstTokenTime | run.first_token_time | 重命名为 snake_case |
run.latency | run.latency_seconds | 已重命名;曾是计算属性,现在是原生 number 字段(秒) |
run.inDataset | run.is_in_dataset | 已重命名 |
run.childRunIds | (已移除) | 无对应项 |
run.childRuns | (已移除) | 无对应项 |
run.serialized | (已移除) | 请使用 run.manifest |
run.manifestId | (已移除) | 请使用 run.manifest |
run.shareToken | (已移除) | 请使用 run.share_url(完整 URL,仅当运行记录被分享时设置) |
| (之前不可用) | run.is_root | 新增 |
| (之前不可用) | run.manifest | 新增:完整的清单对象(替代 serialized 和 manifestId) |
| (之前不可用) | run.error_preview | 新增:截断的错误片段 |
| (之前不可用) | run.inputs_preview | 新增:截断的输入预览 |
| (之前不可用) | run.outputs_preview | 新增:截断的输出预览 |
| (之前不可用) | run.thread_id | 新增:对话线程 UUID |
| (之前不可用) | run.reference_dataset_id | 新增:参考示例的数据集 UUID |
| (之前不可用) | run.share_url | 新增:公共分享 URL(仅当运行记录被分享时设置) |
| (之前不可用) | run.prompt_token_details | 新增:按类别的提示令牌明细 |
| (之前不可用) | run.completion_token_details | 新增:按类别的完成令牌明细 |
| (之前不可用) | run.prompt_cost_details | 新增:按类别的提示成本明细 |
| (之前不可用) | run.completion_cost_details | 新增:按类别的完成成本明细 |
通过
.addSelect(...) 添加 RunQueryV2Params.Select 值(例如 Select.NAME、Select.STATUS)以控制填充哪些字段;未选中的字段返回空的 Optional 值。selects() 默认仅包含 ID。之前 (RunSchema 方法) | 之后 (Run 方法) | 说明 |
|---|---|---|
run.id() | run.id() | 未更改 |
run.name() | run.name() | 未更改 |
run.runType() | run.runType() | 值现在大写:"LLM"、"CHAIN" 等 |
run.status() | run.status() | 值:"SUCCESS"、"ERROR"、"PENDING" |
run.startTime() | run.startTime() | 未更改 |
run.endTime() | run.endTime() | 未更改 |
run.error() | run.error() | 未更改 |
run.inputs() | run.inputs() | 未更改 |
run.outputs() | run.outputs() | 未更改 |
run.tags() | run.tags() | 未更改 |
run.extra() | run.extra() | 未更改 |
run.events() | run.events() | 未更改 |
run.feedbackStats() | run.feedbackStats() | 未更改 |
run.inputsPreview() | run.inputsPreview() | 未更改 |
run.outputsPreview() | run.outputsPreview() | 未更改 |
run.referenceExampleId() | run.referenceExampleId() | 未更改 |
run.traceId() | run.traceId() | 未更改 |
run.dottedOrder() | run.dottedOrder() | 未更改 |
run.parentRunId() | (已移除) | 请使用 run.parentRunIds()(所有祖先 UUID 的列表,根在先) |
run.parentRunIds() | run.parentRunIds() | 未更改 |
run.sessionId() | run.projectId() | 已重命名;sessionId() 返回项目 UUID |
run.appPath() | run.appPath() | 未更改 |
run.firstTokenTime() | run.firstTokenTime() | 未更改 |
run.totalTokens() | run.totalTokens() | 未更改 |
run.promptTokens() | run.promptTokens() | 未更改 |
run.completionTokens() | run.completionTokens() | 未更改 |
run.totalCost() | run.totalCost() | 返回类型从 Optional<String> 更改为 Optional<Double> |
run.promptCost() | run.promptCost() | 返回类型从 Optional<String> 更改为 Optional<Double> |
run.completionCost() | run.completionCost() | 返回类型从 Optional<String> 更改为 Optional<Double> |
run.promptTokenDetails() | run.promptTokenDetails() | 未更改 |
run.completionTokenDetails() | run.completionTokenDetails() | 未更改 |
run.promptCostDetails() | run.promptCostDetails() | 未更改 |
run.completionCostDetails() | run.completionCostDetails() | 未更改 |
run.priceModelId() | run.priceModelId() | 未更改 |
run.inDataset() | run.isInDataset() | 已重命名 |
run.referenceDatasetId() | run.referenceDatasetId() | 未更改 |
run.threadId() | run.threadId() | 未更改 |
run.shareToken() | (已移除) | 请使用 run.shareUrl()(完整 URL,仅当运行记录被分享时设置) |
run.childRunIds() | (已移除) | 无对应项 |
run.directChildRunIds() | (已移除) | 无对应项 |
run.serialized() | (已移除) | 请使用 run.manifest() |
run.manifestId() | (已移除) | 请使用 run.manifest() |
run.messages() | (已移除) | 无对应项 |
run.executionOrder() | (已移除) | 无对应项 |
run.lastQueuedAt() | (已移除) | 无对应项 |
run.traceFirstReceivedAt() | (已移除) | 无对应项 |
run.traceMaxStartTime() | (已移除) | 无对应项 |
run.traceMinStartTime() | (已移除) | 无对应项 |
run.traceTier() | (已移除) | 无对应项 |
run.traceUpgrade() | (已移除) | 无对应项 |
run.ttlSeconds() | (已移除) | 无对应项 |
| (之前不可用) | run.attachments() | 新增:附件的预签名下载 URL(替代 S3 URL 字段) |
| (之前不可用) | run.latencySeconds() | 新增:以秒为单位的时钟耗时 |
| (之前不可用) | run.isRoot() | 新增 |
| (之前不可用) | run.errorPreview() | 新增:截断的错误片段 |
| (之前不可用) | run.manifest() | 新增:完整的清单,类型为 Optional<Manifest>(替代 serialized() 和 manifestId()) |
| (之前不可用) | run.metadata() | 新增:元数据,类型为 Optional<Metadata>(曾派生自 extra.metadata) |
| (之前不可用) | run.shareUrl() | 新增:公共分享 URL(仅当运行记录被分享时设置) |
| (之前不可用) | run.threadEvaluationTime() | 新增 |
向
Selects 传递 RunQueryV2ParamsSelect 常量(例如 RunQueryV2ParamsSelectName、RunQueryV2ParamsSelectStatus)以控制填充哪些字段;未选中的字段在返回的结构体上为零值。Selects 默认仅包含 ID。之前 (RunSchema 字段) | 之后 (Run 字段) | 说明 |
|---|---|---|
run.ID | run.ID | 未更改 |
run.Name | run.Name | 未更改 |
run.RunType | run.RunType | 值更改为大写:"LLM"、"CHAIN" 等 |
run.Status | run.Status | 值:"SUCCESS"、"ERROR"、"PENDING" |
run.TraceID | run.TraceID | 未更改 |
run.DottedOrder | run.DottedOrder | 未更改 |
run.AppPath | run.AppPath | 未更改 |
run.StartTime | run.StartTime | 未更改 |
run.EndTime | run.EndTime | 未更改 |
run.Error | run.Error | 未更改 |
run.Events | run.Events | 未更改;元素类型现在是 RunEvent(曾是 map[string]interface{}) |
run.Extra | run.Extra | 未更改;类型现在是 interface{}(曾是 map[string]interface{}) |
run.FeedbackStats | run.FeedbackStats | 未更改;元素类型现在是 RunFeedbackStat |
run.FirstTokenTime | run.FirstTokenTime | 未更改 |
run.Inputs | run.Inputs | 未更改;类型现在是 interface{}(曾是 map[string]interface{}) |
run.InputsPreview | run.InputsPreview | 未更改 |
run.Outputs | run.Outputs | 未更改;类型现在是 interface{}(曾是 map[string]interface{}) |
run.OutputsPreview | run.OutputsPreview | 未更改 |
run.ParentRunIDs | run.ParentRunIDs | 未更改 |
run.PriceModelID | run.PriceModelID | 未更改 |
run.PromptCost | run.PromptCost | 未更改 |
run.PromptCostDetails | run.PromptCostDetails.Raw | 字段现在包装了该映射;访问 .Raw 以获取 map[string]float64(曾是 map[string]string) |
run.PromptTokenDetails | run.PromptTokenDetails.Raw | 字段现在包装了该映射;访问 .Raw 以获取 map[string]int64(元素类型未更改) |
run.PromptTokens | run.PromptTokens | 未更改 |
run.CompletionCost | run.CompletionCost | 未更改 |
run.CompletionCostDetails | run.CompletionCostDetails.Raw | 字段现在包装了该映射;访问 .Raw 以获取 map[string]float64(曾是 map[string]string) |
run.CompletionTokenDetails | run.CompletionTokenDetails.Raw | 字段现在包装了该映射;访问 .Raw 以获取 map[string]int64(元素类型未更改) |
run.CompletionTokens | run.CompletionTokens | 未更改 |
run.TotalCost | run.TotalCost | 未更改 |
run.TotalTokens | run.TotalTokens | 未更改 |
run.ReferenceDatasetID | run.ReferenceDatasetID | 未更改 |
run.ReferenceExampleID | run.ReferenceExampleID | 未更改 |
run.Tags | run.Tags | 未更改 |
run.ThreadID | run.ThreadID | 未更改 |
run.SessionID | run.ProjectID | 已重命名 |
run.InDataset | run.IsInDataset | 已重命名 |
run.ChildRunIDs | (已移除) | 无对应项 |
run.DirectChildRunIDs | (已移除) | 无对应项 |
run.ExecutionOrder | (已移除) | 无对应项 |
run.InputsS3URLs | (已移除) | 内部存储 URL;未在 v2 中公开 |
run.LastQueuedAt | (已移除) | 无对应项 |
run.ManifestID | (已移除) | 请使用 run.Manifest |
run.ManifestS3ID | (已移除) | 内部存储 URL;未在 v2 中公开 |
run.Messages | (已移除) | 无对应项 |
run.OutputsS3URLs | (已移除) | 内部存储 URL;未在 v2 中公开 |
run.ParentRunID | (已移除) | 请使用 run.ParentRunIDs |
run.S3URLs | (已移除) | 内部存储 URL;未在 v2 中公开 |
run.Serialized | (已移除) | 请使用 run.Manifest |
run.ShareToken | (已移除) | 请使用 run.ShareURL |
run.TraceFirstReceivedAt | (已移除) | 无对应项 |
run.TraceMaxStartTime | (已移除) | 无对应项 |
run.TraceMinStartTime | (已移除) | 无对应项 |
run.TraceTier | (已移除) | 无对应项 |
run.TraceUpgrade | (已移除) | 无对应项 |
run.TtlSeconds | (已移除) | 无对应项 |
| (之前不可用) | run.Attachments | 新增:将附件文件名映射到预签名的下载 URL |
| (之前不可用) | run.ErrorPreview | 新增:截断的错误片段 |
| (之前不可用) | run.IsRoot | 新增 |
| (之前不可用) | run.LatencySeconds | 新增:以秒为单位的时钟耗时 |
| (之前不可用) | run.Manifest | 新增:完整的清单对象(替代 Serialized 和 ManifestID) |
| (之前不可用) | run.Metadata | 新增:任意的用户定义 JSON 元数据 |
| (之前不可用) | run.ShareURL | 新增:公共分享 URL(仅当运行记录被分享时设置) |
| (之前不可用) | run.ThreadEvaluationTime | 新增 |
JSON 响应中的字段名使用
snake_case。在 selects JSON 数组中传递 SCREAMING_SNAKE_CASE 字符串(例如 "ID"、"NAME"、"STATUS")以控制填充哪些字段。默认的 selects 仅包含 "ID"。| 之前 (v1 响应字段) | 之后 (v2 响应字段) | 说明 |
|---|---|---|
id | id | 未更改 |
name | name | 未更改 |
run_type | run_type | 值更改为大写:"LLM"、"CHAIN" 等 |
status | status | 值:"SUCCESS"、"ERROR"、"PENDING" |
trace_id | trace_id | 未更改 |
dotted_order | dotted_order | 未更改 |
app_path | app_path | 未更改 |
start_time | start_time | 未更改 |
end_time | end_time | 未更改 |
error | error | 未更改 |
events | events | 未更改 |
extra | extra | 未更改 |
feedback_stats | feedback_stats | 未更改 |
first_token_time | first_token_time | 未更改 |
inputs | inputs | 未更改 |
inputs_preview | inputs_preview | 未更改 |
outputs | outputs | 未更改 |
outputs_preview | outputs_preview | 未更改 |
parent_run_ids | parent_run_ids | 未更改 |
price_model_id | price_model_id | 未更改 |
prompt_cost | prompt_cost | 未更改 |
prompt_cost_details | prompt_cost_details.raw | 字段现在包装了该对象;读取 .raw 以获取相同的 {category: cost} 映射,现在是数值(曾是字符串) |
prompt_token_details | prompt_token_details.raw | 字段现在包装了该对象;读取 .raw 以获取相同的 {category: count} 映射(值未更改) |
prompt_tokens | prompt_tokens | 未更改 |
completion_cost | completion_cost | 未更改 |
completion_cost_details | completion_cost_details.raw | 字段现在包装了该对象;读取 .raw 以获取相同的 {category: cost} 映射,现在是数值(曾是字符串) |
completion_token_details | completion_token_details.raw | 字段现在包装了该对象;读取 .raw 以获取相同的 {category: count} 映射(值未更改) |
completion_tokens | completion_tokens | 未更改 |
total_cost | total_cost | 未更改 |
total_tokens | total_tokens | 未更改 |
reference_dataset_id | reference_dataset_id | 未更改 |
reference_example_id | reference_example_id | 未更改 |
tags | tags | 未更改 |
thread_id | thread_id | 未更改 |
session_id | project_id | 已重命名 |
in_dataset | is_in_dataset | 已重命名 |
child_run_ids | (已移除) | 无对应项 |
direct_child_run_ids | (已移除) | 无对应项 |
execution_order | (已移除) | 无对应项 |
inputs_s3_urls | (已移除) | 内部存储 URL;未在 v2 中公开 |
last_queued_at | (已移除) | 无对应项 |
manifest_id | (已移除) | 请使用 manifest |
manifest_s3_id | (已移除) | 内部存储 URL;未在 v2 中公开 |
messages | (已移除) | 无对应项 |
outputs_s3_urls | (已移除) | 内部存储 URL;未在 v2 中公开 |
parent_run_id | (已移除) | 请使用 parent_run_ids |
s3_urls | (已移除) | 内部存储 URL;未在 v2 中公开 |
serialized | (已移除) | 请使用 manifest |
share_token | (已移除) | 请使用 share_url |
trace_first_received_at | (已移除) | 无对应项 |
trace_max_start_time | (已移除) | 无对应项 |
trace_min_start_time | (已移除) | 无对应项 |
trace_tier | (已移除) | 无对应项 |
trace_upgrade | (已移除) | 无对应项 |
ttl_seconds | (已移除) | 无对应项 |
| (之前不可用) | attachments | 新增:将附件文件名映射到预签名的下载 URL |
| (之前不可用) | error_preview | 新增:截断的错误片段 |
| (之前不可用) | is_root | 新增 |
| (之前不可用) | latency_seconds | 新增:以秒为单位的时钟耗时 |
| (之前不可用) | manifest | 新增:完整的清单对象(替代 serialized 和 manifest_id) |
| (之前不可用) | metadata | 新增:之前嵌套在 extra.metadata 下 |
| (之前不可用) | share_url | 新增:公共分享 URL(仅当运行记录被分享时设置) |
| (之前不可用) | thread_evaluation_time | 新增 |
示例
列出项目中的所有运行记录
- Python
- TypeScript
- Java
- Go
- cURL
runs.query 不直接接受项目名称。请先使用 client.aread_project() 解析项目 UUID,然后将其作为字符串传递给 project_ids。- Before
- After
client.runs.query 不直接接受项目名称。请先使用 client.readProject() 解析项目 UUID,然后将其作为字符串传递给 project_ids。- Before
- After
queryV2() 不直接接受项目名称。请先使用 client.sessions().list() 解析项目 UUID,然后将其作为字符串传递给 projectIds()。- Before
- After
QueryV2() 不直接接受项目名称。请先使用 client.Sessions.List() 解析项目 UUID,然后将其作为字符串传递给 ProjectIDs。- Before
- After
POST /api/v2/runs/query 不直接接受项目名称。请先通过 GET /api/v1/sessions 请求解析项目 UUID,然后将其作为字符串传递给 project_ids。- Before
- After
选择字段
- Python
- TypeScript
- Java
- Go
- cURL
list_runs 返回一组默认字段,无需选择。runs.query 默认只返回 id——传递 selects=[...] 以请求更多字段。字段名现在是大写的("name" → "NAME")。- Before
- After
listRuns 返回一组默认字段,无需选择。client.runs.query 默认只返回 id——传递 selects: [...] 以请求更多字段。字段名现在是大写的("name" → "NAME")。- Before
- After
query() 返回一组默认字段,无需选择。queryV2() 默认只返回 id——为每个需要的字段调用 .addSelect(RunQueryV2Params.Select.X)。- Before
- After
Query 返回一组默认字段,无需选择。QueryV2 默认只返回 ID——传递包含你需要的大写字段常量的 Selects(例如 RunQueryV2ParamsSelectName)。- Before
- After
POST /api/v1/runs/query 返回一组默认字段,无需选择。POST /api/v2/runs/query 默认只返回 id——在 selects 中传递你需要的大写字段名(例如 "NAME")。- Before
- After
按运行类型和时间范围筛选
- Python
- TypeScript
- Java
- Go
- cURL
start_time 重命名为 min_start_time,且 run_type 的值现在是大写的("llm" → "LLM")。- Before
- After
startTime (camelCase) 变为 min_start_time (snake_case,与 v2 请求体匹配),且 runType 的值现在是大写的("llm" → "LLM")。- Before
- After
.startTime() 重命名为 .minStartTime(),且 .runType() 现在接受新的 RunQueryV2Params.RunType 枚举,而非 RunTypeEnum。- Before
- After
StartTime 重命名为 MinStartTime,且 RunType 现在接受新的 RunQueryV2ParamsRunType 枚举,而非 RunTypeEnum。- Before
- After
start_time 重命名为 min_start_time,且 run_type 的值现在是大写的("llm" → "LLM")。- Before
- After
仅筛选根运行记录
- Python
- TypeScript
- Java
- Go
- cURL
is_root 保持不变。- Before
- After
isRoot (camelCase) 变为 is_root (snake_case,与 v2 请求体匹配)。- Before
- After
.isRoot() 保持不变。- Before
- After
IsRoot 保持不变。- Before
- After
is_root 保持不变。- Before
- After
若要专门枚举追踪,请使用
traces.query 而非 is_root=True。参见 追踪:查询:它还通过 trace_aggregates 提供了整个追踪级别的 total_tokens/total_cost。通过 ID 列表获取运行记录
- Python
- TypeScript
- Java
- Go
- cURL
id=[...] 重命名为 ids=[...]。即使按运行 ID 筛选,project_ids 现在也是必需的——v1 允许省略项目上下文。- Before
- After
id: [...] 重命名为 ids: [...]。即使按运行 ID 筛选,project_ids 现在也是必需的——v1 允许省略项目上下文。- Before
- After
.addId(...) 保持不变——为每个运行 ID 调用一次。即使按运行 ID 筛选,.addProjectId(...) 现在也是必需的——v1 允许省略项目上下文。- Before
- After
ID: [...] 重命名为 IDs: [...]。即使按运行 ID 筛选,ProjectIDs 现在也是必需的——v1 允许省略项目上下文。- Before
- After
id 重命名为 ids。即使按运行 ID 筛选,project_ids 现在在请求体中也是必需的——v1 允许省略项目上下文。- Before
- After
迭代运行记录
- Python
- TypeScript
- Java
- Go
- cURL
list_runs 自动处理分页,每次 API 调用最多获取 100 条运行记录,并在返回 limit 条结果后停止。runs.query 不接受总 limit 参数;使用 async for 迭代,并在获得足够数据后使用 break 退出,或使用返回页面的 has_next_page()/get_next_page() 进行手动逐页控制。- Before
- After
listRuns 自动处理分页。client.runs.query 返回单个运行记录的异步可迭代对象——使用 for await 迭代,并在获得足够数据后使用 break 退出。- Before
- After
.autoPager() 在 query() 和 queryV2() 上的用法相同——在获得足够运行记录后跳出循环。- Before
- After
QueryAutoPaging 重命名为 QueryV2AutoPaging;两者都使用相同的 iter.Next()/iter.Current() 模式——在获得足够运行记录后跳出循环。- Before
- After
v1 API 在单个响应中返回所有匹配的运行记录,无游标。v2 API 进行分页——将响应中
next_cursor 字段的 cursor 值传递下去以获取下一页。- Before
- After
筛选包含错误的运行记录
- Python
- TypeScript
- Java
- Go
- cURL
error=True/False 重命名为 has_error=True/False。- Before
- After
error: true/false 重命名为 has_error: true/false。- Before
- After
.error(true/false) 重命名为 .hasError(true/false)。- Before
- After
Error 重命名为 HasError。- Before
- After
error 重命名为 has_error。- Before
- After
按元数据筛选
- Python
- TypeScript
- Java
- Go
- cURL
filter 字符串语法保持不变:eq(metadata_key, ...) 检查键是否存在,与 eq(metadata_value, ...) 组合以匹配特定值。- Before
- After
filter 字符串语法保持不变:eq(metadata_key, ...) 检查键是否存在,与 eq(metadata_value, ...) 组合以匹配特定值。- Before
- After
.filter(...) 字符串语法保持不变:eq(metadata_key, ...) 检查键是否存在,与 eq(metadata_value, ...) 组合以匹配特定值。- Before
- After
Filter 字符串语法保持不变:eq(metadata_key, ...) 检查键是否存在,与 eq(metadata_value, ...) 组合以匹配特定值。- Before
- After
filter 字符串语法保持不变:eq(metadata_key, ...) 检查键是否存在,与 eq(metadata_value, ...) 组合以匹配特定值。- Before
- After
复杂的布尔筛选器
- Python
- TypeScript
- Java
- Go
- cURL
嵌套的
and() / or() 筛选表达式保持不变。- Before
- After
嵌套的
and() / or() 筛选表达式保持不变。- Before
- After
嵌套的
and() / or() 筛选表达式保持不变。- Before
- After
嵌套的
and() / or() 筛选表达式保持不变。- Before
- After
嵌套的
and() / or() 筛选表达式保持不变。- Before
- After
范围筛选器:filter、trace_filter、tree_filter
- Python
- TypeScript
- Java
- Go
- cURL
filter、trace_filter 和 tree_filter 保持不变。filter 适用于匹配的运行记录,trace_filter 适用于其追踪的根记录,tree_filter 适用于追踪树中的其他运行记录(同级和子级)。- Before
- After
filter、trace_filter 和 tree_filter 保持不变。filter 适用于匹配的运行记录,trace_filter 适用于其追踪的根记录,tree_filter 适用于追踪树中的其他运行记录(同级和子级)。- Before
- After
.filter()、.traceFilter() 和 .treeFilter() 保持不变。filter 适用于匹配的运行记录,traceFilter 适用于其追踪的根记录,treeFilter 适用于追踪树中的其他运行记录(同级和子级)。- Before
- After
Filter、TraceFilter 和 TreeFilter 保持不变。Filter 适用于匹配的运行记录,TraceFilter 适用于其追踪的根记录,TreeFilter 适用于追踪树中的其他运行记录(同级和子级)。- Before
- After
filter、trace_filter 和 tree_filter 保持不变。filter 适用于匹配的运行记录,trace_filter 适用于其追踪的根记录,tree_filter 适用于追踪树中的其他运行记录(同级和子级)。- Before
- After
运行:获取
通过 ID 获取单个运行。默认仅返回运行 ID——指定字段选择列表以检索更多数据。主要变更
方法名称
- Python
- TypeScript
- Java
- Go
- cURL
| 变更前 | 变更后 |
|---|---|
client.read_run() | client.runs.retrieve() |
client.runs.retrieve() 现在是异步的。调用时需要使用 await。| 变更前 | 变更后 |
|---|---|
client.readRun() | client.runs.retrieve() |
| 变更前 | 变更后 |
|---|---|
client.runs().retrieve() | client.runs().retrieveV2() |
| 变更前 | 变更后 |
|---|---|
client.Runs.Get() | client.Runs.GetV2() |
| 变更前 | 变更后 |
|---|---|
GET /api/v1/runs/{run_id} | GET /api/v2/runs/{run_id} |
查询参数
- Python
- TypeScript
- Java
- Go
- cURL
runs.retrieve 需要一个新的 project_id 字段,这是 read_run 不需要的。它还接受一个可选的 start_time——提供该参数可以加快检索速度,但并非必需。变更前 (read_run) | 变更后 (runs.retrieve) | 备注 |
|---|---|---|
run_id | run_id | 不变 |
load_child_runs | (已移除) | 使用 traces.list_runs 获取追踪中的运行,并通过 parent_run_ids 进行过滤。参见 加载运行的子运行 |
| (不可用) | project_id | 必填 — 拥有该运行的项目的 UUID |
| (不可用) | start_time | 可选 — 运行的开始时间(RFC3339 格式);提供该参数可以加快检索速度 |
| (默认返回所有字段) | selects | 字段投影;默认仅包含 ["ID"];字段名为大写 |
client.runs.retrieve 需要一个新的 project_id 字段,这是 readRun 不需要的。它还接受一个可选的 start_time——提供该参数可以加快检索速度,但并非必需。变更前 (readRun) | 变更后 (client.runs.retrieve) | 备注 |
|---|---|---|
runId | runId | 不变(位置参数) |
options.loadChildRuns | (已移除) | 使用 client.traces.listRuns 获取追踪中的运行,并通过 parent_run_ids 进行过滤。参见 加载运行的子运行 |
| (不可用) | project_id | 必填 — snake_case 格式;拥有该运行的项目的 UUID |
| (不可用) | start_time | 可选 — snake_case 格式;运行的开始时间(RFC3339 格式);提供该参数可以加快检索速度 |
| (默认返回所有字段) | selects | 字段投影;默认仅包含 ["ID"];字段名为大写 |
retrieveV2() 需要 projectId(),它替代了已移除的 sessionId()。startTime() 仍然是可选的——提供该参数可以加快检索速度,但并非必需。变更前 (RunRetrieveParams) | 变更后 (RunRetrieveV2Params) | 备注 |
|---|---|---|
runId() | runId() | 不变 |
sessionId() | (已移除) | 被 projectId() 替代 |
startTime() | startTime() | 仍然是可选的;提供该参数可以加快检索速度 |
excludeS3StoredAttributes() | (已移除) | 无对应项 |
excludeSerialized() | (已移除) | 无对应项 |
includeMessages() | (已移除) | 无对应项 |
| (不可用) | projectId() | 必填 — 拥有该运行的项目的 UUID |
| (默认返回所有字段) | selects() | 字段投影;默认仅包含 ["ID"];字段名为大写 |
GetV2() 需要 ProjectID,它替代了已移除的 SessionID。StartTime 仍然是可选的——提供该参数可以加快检索速度,但并非必需。变更前 (RunGetParams) | 变更后 (RunGetV2Params) | 备注 |
|---|---|---|
runID (位置参数) | runID (位置参数) | 不变 |
ExcludeS3StoredAttributes | (已移除) | 无对应项 |
ExcludeSerialized | (已移除) | 无对应项 |
IncludeMessages | (已移除) | 无对应项 |
SessionID | (已移除) | 被 ProjectID 替代 |
StartTime | StartTime | 仍然是可选的;提供该参数可以加快检索速度 |
| (不可用) | ProjectID | 必填 — 拥有该运行的项目的 UUID |
| (默认返回所有字段) | Selects | 字段投影;默认仅包含 ["ID"];字段名常量为大写(例如,RunGetV2ParamsSelectName) |
run_id 保留在 URL 路径中。所有其他参数都是使用 snake_case 命名的查询字符串值。GET /api/v2/runs/{run_id} 需要一个新的 project_id 查询参数。start_time 仍然是可选的——提供该参数可以加快检索速度,但并非必需。变更前 (GET /api/v1/runs/{run_id} 参数) | 变更后 (GET /api/v2/runs/{run_id} 参数) | 备注 |
|---|---|---|
run_id (路径) | run_id (路径) | 不变 |
| (不可用) | project_id (查询) | 必填 — 拥有该运行的项目的 UUID |
start_time (查询) | start_time (查询) | 仍然是可选的;提供该参数可以加快检索速度 |
| (默认返回所有字段) | selects (查询, 可重复) | 字段投影;默认仅包含 ["ID"];字段名为大写 |
响应字段
- Python
- TypeScript
- Java
- Go
- cURL
传递 SCREAMING_SNAKE_CASE 格式的字符串给
selects(例如 "ID", "NAME", "STATUS")以控制返回的 Run 对象上哪些字段被填充;只有被选中的字段才非 None。默认的 selects 仅包含 "ID"。变更前 (v1 Run 属性) | 变更后 (v2 Run 属性) | 备注 |
|---|---|---|
run.id | run.id | 不变;省略 selects 时默认返回 |
run.name | run.name | 不变 |
run.run_type | run.run_type | 值现在是大小写字面量:"LLM", "CHAIN" 等 |
run.status | run.status | 值:"SUCCESS", "ERROR", "PENDING" |
run.start_time | run.start_time | 不变 |
run.end_time | run.end_time | 不变 |
run.error | run.error | 不变 |
run.inputs | run.inputs | 不变 |
run.outputs | run.outputs | 不变 |
run.tags | run.tags | 不变 |
run.extra | run.extra | 不变 |
run.metadata | run.metadata | 不变 |
run.events | run.events | 不变 |
run.reference_example_id | run.reference_example_id | 不变 |
run.trace_id | run.trace_id | 不变 |
run.dotted_order | run.dotted_order | 不变 |
run.parent_run_id | (已移除) | 使用 run.parent_run_ids(所有祖先 UUID 的列表,根节点在前) |
run.parent_run_ids | run.parent_run_ids | 不变 |
run.session_id | run.project_id | 已重命名;session_id 是项目 UUID |
run.feedback_stats | run.feedback_stats | 不变 |
run.app_path | run.app_path | 不变 |
run.attachments | run.attachments | v2 返回预签名的下载 URL,而非原始字节 |
run.total_tokens | run.total_tokens | 不变 |
run.prompt_tokens | run.prompt_tokens | 不变 |
run.completion_tokens | run.completion_tokens | 不变 |
run.total_cost | run.total_cost | 不变 |
run.prompt_cost | run.prompt_cost | 不变 |
run.completion_cost | run.completion_cost | 不变 |
run.first_token_time | run.first_token_time | 不变 |
run.latency (属性) | run.latency_seconds | 已重命名;是一个计算的 timedelta 属性,现在是原生 float 字段 |
run.in_dataset | run.is_in_dataset | 已重命名 |
run.child_run_ids | (已移除) | 在追踪的运行上按 parent_run_ids 过滤。参见 加载运行的子运行 |
run.child_runs | (已移除) | 按 parent_run_ids 的最后一项对追踪的运行进行分组。参见 加载运行的子运行 |
run.serialized | (已移除) | 使用 run.manifest |
run.manifest_id | (已移除) | 使用 run.manifest |
| (不可用) | run.is_root | 新增 |
| (不可用) | run.manifest | 新增:完整的清单对象(替代 serialized 和 manifest_id) |
| (不可用) | run.error_preview | 新增:截断的错误片段 |
| (不可用) | run.inputs_preview | 新增:截断的输入预览 |
| (不可用) | run.outputs_preview | 新增:截断的输出预览 |
| (不可用) | run.thread_id | 新增:会话线程 UUID |
| (不可用) | run.reference_dataset_id | 新增:参考示例的数据集 UUID |
| (不可用) | run.share_url | 新增:公开分享 URL(仅在运行已分享时设置) |
run.prompt_token_details | run.prompt_token_details.raw | 字段现在包装了字典;访问 .raw 以获取 dict[str, int](元素类型不变) |
run.completion_token_details | run.completion_token_details.raw | 字段现在包装了字典;访问 .raw 以获取 dict[str, int](元素类型不变) |
run.prompt_cost_details | run.prompt_cost_details.raw | 字段现在包装了字典;访问 .raw 以获取 dict[str, float](原来是 dict[str, Decimal]) |
run.completion_cost_details | run.completion_cost_details.raw | 字段现在包装了字典;访问 .raw 以获取 dict[str, float](原来是 dict[str, Decimal]) |
传递 SCREAMING_SNAKE_CASE 格式的字符串给
selects(例如 "ID", "NAME", "STATUS")以控制返回的 Run 对象上哪些字段被填充。默认的 selects 仅包含 "ID"。变更前 (v1 Run 属性) | 变更后 (v2 Run 属性) | 备注 |
|---|---|---|
run.id | run.id | 不变 |
run.name | run.name | 不变 |
run.runType | run.run_type | 重命名为 snake_case;值现在是大写:"LLM", "CHAIN" 等 |
run.status | run.status | 值:"SUCCESS", "ERROR", "PENDING" |
run.startTime | run.start_time | 重命名为 snake_case |
run.endTime | run.end_time | 重命名为 snake_case |
run.error | run.error | 不变 |
run.inputs | run.inputs | 不变 |
run.outputs | run.outputs | 不变 |
run.tags | run.tags | 不变 |
run.extra | run.extra | 不变 |
| (不可用) | run.metadata | 新增:之前通过 run.extra.metadata 访问 |
run.events | run.events | 不变 |
run.referenceExampleId | run.reference_example_id | 重命名为 snake_case |
run.traceId | run.trace_id | 重命名为 snake_case |
run.dottedOrder | run.dotted_order | 重命名为 snake_case |
run.parentRunId | (已移除) | 使用 run.parent_run_ids(所有祖先 UUID 的列表,根节点在前) |
run.parentRunIds | run.parent_run_ids | 重命名为 snake_case |
run.sessionId | run.project_id | 已重命名;sessionId 是项目 UUID |
run.feedbackStats | run.feedback_stats | 重命名为 snake_case |
run.appPath | run.app_path | 重命名为 snake_case |
run.attachments | run.attachments | v2 返回预签名的下载 URL,而非原始字节 |
run.totalTokens | run.total_tokens | 重命名为 snake_case |
run.promptTokens | run.prompt_tokens | 重命名为 snake_case |
run.completionTokens | run.completion_tokens | 重命名为 snake_case |
run.totalCost | run.total_cost | 重命名为 snake_case |
run.promptCost | run.prompt_cost | 重命名为 snake_case |
run.completionCost | run.completion_cost | 重命名为 snake_case |
run.firstTokenTime | run.first_token_time | 重命名为 snake_case |
run.latency | run.latency_seconds | 已重命名;是一个计算属性,现在是原生 number 字段(秒) |
run.inDataset | run.is_in_dataset | 已重命名 |
run.child_run_ids | (已移除) | 在追踪的运行上按 parent_run_ids 过滤。参见 加载运行的子运行 |
run.child_runs | (已移除) | 按 parent_run_ids 的最后一项对追踪的运行进行分组。参见 加载运行的子运行 |
run.serialized | (已移除) | 使用 run.manifest |
run.manifestId | (已移除) | 使用 run.manifest |
run.shareToken | (已移除) | 使用 run.share_url(完整 URL,仅在运行已分享时设置) |
| (不可用) | run.is_root | 新增 |
| (不可用) | run.manifest | 新增:完整的清单对象(替代 serialized 和 manifestId) |
| (不可用) | run.error_preview | 新增:截断的错误片段 |
| (不可用) | run.inputs_preview | 新增:截断的输入预览 |
| (不可用) | run.outputs_preview | 新增:截断的输出预览 |
| (不可用) | run.thread_id | 新增:会话线程 UUID |
| (不可用) | run.reference_dataset_id | 新增:参考示例的数据集 UUID |
| (不可用) | run.share_url | 新增:公开分享 URL(仅在运行已分享时设置) |
| (不可用) | run.prompt_token_details | 新增:按类别的提示词 token 明细 |
| (不可用) | run.completion_token_details | 新增:按类别的补全 token 明细 |
| (不可用) | run.prompt_cost_details | 新增:按类别的提示词成本明细 |
| (不可用) | run.completion_cost_details | 新增:按类别的补全成本明细 |
通过
.addSelect(...) 添加 RunRetrieveV2Params.Select 值(例如 Select.NAME, Select.STATUS)以控制哪些字段被填充;未选中的字段返回空的 Optional 值。selects() 默认仅包含 ID。变更前 (RunSchema 方法) | 变更后 (Run 方法) | 备注 |
|---|---|---|
run.id() | run.id() | 不变 |
run.name() | run.name() | 不变 |
run.runType() | run.runType() | 值现在是大写:"LLM", "CHAIN" 等 |
run.status() | run.status() | 值:"SUCCESS", "ERROR", "PENDING" |
run.startTime() | run.startTime() | 不变 |
run.endTime() | run.endTime() | 不变 |
run.error() | run.error() | 不变 |
run.inputs() | run.inputs() | 不变 |
run.outputs() | run.outputs() | 不变 |
run.tags() | run.tags() | 不变 |
run.extra() | run.extra() | 不变 |
run.events() | run.events() | 不变 |
run.feedbackStats() | run.feedbackStats() | 不变 |
run.inputsPreview() | run.inputsPreview() | 不变 |
run.outputsPreview() | run.outputsPreview() | 不变 |
run.referenceExampleId() | run.referenceExampleId() | 不变 |
run.traceId() | run.traceId() | 不变 |
run.dottedOrder() | run.dottedOrder() | 不变 |
run.parentRunId() | (已移除) | 使用 run.parentRunIds()(所有祖先 UUID 的列表,根节点在前) |
run.parentRunIds() | run.parentRunIds() | 不变 |
run.sessionId() | run.projectId() | 已重命名;sessionId() 返回的是项目 UUID |
run.appPath() | run.appPath() | 不变 |
run.firstTokenTime() | run.firstTokenTime() | 不变 |
run.totalTokens() | run.totalTokens() | 不变 |
run.promptTokens() | run.promptTokens() | 不变 |
run.completionTokens() | run.completionTokens() | 不变 |
run.totalCost() | run.totalCost() | 返回类型从 Optional<String> 变为 Optional<Double> |
run.promptCost() | run.promptCost() | 返回类型从 Optional<String> 变为 Optional<Double> |
run.completionCost() | run.completionCost() | 返回类型从 Optional<String> 变为 Optional<Double> |
run.promptTokenDetails() | run.promptTokenDetails() | 不变 |
run.completionTokenDetails() | run.completionTokenDetails() | 不变 |
run.promptCostDetails() | run.promptCostDetails() | 不变 |
run.completionCostDetails() | run.completionCostDetails() | 不变 |
run.priceModelId() | run.priceModelId() | 不变 |
run.inDataset() | run.isInDataset() | 已重命名 |
run.referenceDatasetId() | run.referenceDatasetId() | 不变 |
run.threadId() | run.threadId() | 不变 |
run.shareToken() | (已移除) | 使用 run.shareUrl()(完整 URL,仅在运行已分享时设置) |
run.childRunIds() | (已移除) | 无对应项 |
run.directChildRunIds() | (已移除) | 无对应项 |
run.serialized() | (已移除) | 使用 run.manifest() |
run.manifestId() | (已移除) | 使用 run.manifest() |
run.messages() | (已移除) | 无对应项 |
run.executionOrder() | (已移除) | 无对应项 |
run.lastQueuedAt() | (已移除) | 无对应项 |
run.traceFirstReceivedAt() | (已移除) | 无对应项 |
run.traceMaxStartTime() | (已移除) | 无对应项 |
run.traceMinStartTime() | (已移除) | 无对应项 |
run.traceTier() | (已移除) | 无对应项 |
run.traceUpgrade() | (已移除) | 无对应项 |
run.ttlSeconds() | (已移除) | 无对应项 |
| (不可用) | run.attachments() | 新增:附件的预签名下载 URL(替代 S3 URL 字段) |
| (不可用) | run.latencySeconds() | 新增:以秒为单位的时钟持续时间 |
| (不可用) | run.isRoot() | 新增 |
| (不可用) | run.errorPreview() | 新增:截断的错误片段 |
| (不可用) | run.manifest() | 新增:完整的清单,类型为 Optional<Manifest>(替代 serialized() 和 manifestId()) |
| (不可用) | run.metadata() | 新增:元数据,类型为 Optional<Metadata>(之前源自 extra.metadata) |
| (不可用) | run.shareUrl() | 新增:公开分享 URL(仅在运行已分享时设置) |
| (不可用) | run.threadEvaluationTime() | 新增 |
传递
RunGetV2ParamsSelect 常量(例如 RunGetV2ParamsSelectName, RunGetV2ParamsSelectStatus)给 Selects 以控制哪些字段被填充;未选中的字段在返回的结构体上为零值。Selects 默认仅包含 ID。变更前 (RunSchema 字段) | 变更后 (Run 字段) | 备注 |
|---|---|---|
run.ID | run.ID | 不变 |
run.Name | run.Name | 不变 |
run.RunType | run.RunType | 值变为大写:"LLM", "CHAIN" 等 |
run.Status | run.Status | 值:"SUCCESS", "ERROR", "PENDING" |
run.TraceID | run.TraceID | 不变 |
run.DottedOrder | run.DottedOrder | 不变 |
run.AppPath | run.AppPath | 不变 |
run.StartTime | run.StartTime | 不变 |
run.EndTime | run.EndTime | 不变 |
run.Error | run.Error | 不变 |
run.Events | run.Events | 不变;元素类型现在是 RunEvent(原来是 map[string]interface{}) |
run.Extra | run.Extra | 不变;类型现在是 interface{}(原来是 map[string]interface{}) |
run.FeedbackStats | run.FeedbackStats | 不变;元素类型现在是 RunFeedbackStat |
run.FirstTokenTime | run.FirstTokenTime | 不变 |
run.Inputs | run.Inputs | 不变;类型现在是 interface{}(原来是 map[string]interface{}) |
run.InputsPreview | run.InputsPreview | 不变 |
run.Outputs | run.Outputs | 不变;类型现在是 interface{}(原来是 map[string]interface{}) |
run.OutputsPreview | run.OutputsPreview | 不变 |
run.ParentRunIDs | run.ParentRunIDs | 不变 |
run.PriceModelID | run.PriceModelID | 不变 |
run.PromptCost | run.PromptCost | 不变 |
run.PromptCostDetails | run.PromptCostDetails.Raw | 字段现在包装了映射;访问 .Raw 以获取 map[string]float64(原来是 map[string]string) |
run.PromptTokenDetails | run.PromptTokenDetails.Raw | 字段现在包装了映射;访问 .Raw 以获取 map[string]int64(元素类型不变) |
run.PromptTokens | run.PromptTokens | 不变 |
run.CompletionCost | run.CompletionCost | 不变 |
run.CompletionCostDetails | run.CompletionCostDetails.Raw | 字段现在包装了映射;访问 .Raw 以获取 map[string]float64(原来是 map[string]string) |
run.CompletionTokenDetails | run.CompletionTokenDetails.Raw | 字段现在包装了映射;访问 .Raw 以获取 map[string]int64(元素类型不变) |
run.CompletionTokens | run.CompletionTokens | 不变 |
run.TotalCost | run.TotalCost | 不变 |
run.TotalTokens | run.TotalTokens | 不变 |
run.ReferenceDatasetID | run.ReferenceDatasetID | 不变 |
run.ReferenceExampleID | run.ReferenceExampleID | 不变 |
run.Tags | run.Tags | 不变 |
run.ThreadID | run.ThreadID | 不变 |
run.SessionID | run.ProjectID | 已重命名 |
run.InDataset | run.IsInDataset | 已重命名 |
run.ChildRunIDs | (已移除) | 无对应项 |
run.DirectChildRunIDs | (已移除) | 无对应项 |
run.ExecutionOrder | (已移除) | 无对应项 |
run.InputsS3URLs | (已移除) | 内部存储 URL;v2 中不暴露 |
run.LastQueuedAt | (已移除) | 无对应项 |
run.ManifestID | (已移除) | 使用 run.Manifest |
run.ManifestS3ID | (已移除) | 内部存储 URL;v2 中不暴露 |
run.Messages | (已移除) | 无对应项 |
run.OutputsS3URLs | (已移除) | 内部存储 URL;v2 中不暴露 |
run.ParentRunID | (已移除) | 使用 run.ParentRunIDs |
run.S3URLs | (已移除) | 内部存储 URL;v2 中不暴露 |
run.Serialized | (已移除) | 使用 run.Manifest |
run.ShareToken | (已移除) | 使用 run.ShareURL |
run.TraceFirstReceivedAt | (已移除) | 无对应项 |
run.TraceMaxStartTime | (已移除) | 无对应项 |
run.TraceMinStartTime | (已移除) | 无对应项 |
run.TraceTier | (已移除) | 无对应项 |
run.TraceUpgrade | (已移除) | 无对应项 |
run.TtlSeconds | (已移除) | 无对应项 |
| (不可用) | run.Attachments | 新增:将附件文件名映射到预签名下载 URL |
| (不可用) | run.ErrorPreview | 新增:截断的错误片段 |
| (不可用) | run.IsRoot | 新增 |
| (不可用) | run.LatencySeconds | 新增:以秒为单位的时钟持续时间 |
| (不可用) | run.Manifest | 新增:完整的清单对象(替代 Serialized 和 ManifestID) |
| (不可用) | run.Metadata | 新增:任意用户定义的 JSON 元数据 |
| (不可用) | run.ShareURL | 新增:公开分享 URL(仅在运行已分享时设置) |
| (不可用) | run.ThreadEvaluationTime | 新增 |
传递 SCREAMING_SNAKE_CASE 格式的字符串作为可重复的
selects 查询参数(例如 selects=NAME&selects=STATUS)以控制哪些字段被填充。默认的 selects 仅包含 "ID"。| 变更前 (v1 响应字段) | 变更后 (v2 响应字段) | 备注 |
|---|---|---|
id | id | 不变 |
name | name | 不变 |
run_type | run_type | 值变为大写:"LLM", "CHAIN" 等 |
status | status | 值:"SUCCESS", "ERROR", "PENDING" |
trace_id | trace_id | 不变 |
dotted_order | dotted_order | 不变 |
app_path | app_path | 不变 |
start_time | start_time | 不变 |
end_time | end_time | 不变 |
error | error | 不变 |
events | events | 不变 |
extra | extra | 不变 |
feedback_stats | feedback_stats | 不变 |
first_token_time | first_token_time | 不变 |
inputs | inputs | 不变 |
inputs_preview | inputs_preview | 不变 |
outputs | outputs | 不变 |
outputs_preview | outputs_preview | 不变 |
parent_run_ids | parent_run_ids | 不变 |
price_model_id | price_model_id | 不变 |
prompt_cost | prompt_cost | 不变 |
prompt_cost_details | prompt_cost_details.raw | 字段现在包装了对象;读取 .raw 以获取相同的 {category: cost} 映射,现在值是数字类型(原来是字符串) |
prompt_token_details | prompt_token_details.raw | 字段现在包装了对象;读取 .raw 以获取相同的 {category: count} 映射(值不变) |
prompt_tokens | prompt_tokens | 不变 |
completion_cost | completion_cost | 不变 |
completion_cost_details | completion_cost_details.raw | 字段现在包装了对象;读取 .raw 以获取相同的 {category: cost} 映射,现在值是数字类型(原来是字符串) |
completion_token_details | completion_token_details.raw | 字段现在包装了对象;读取 .raw 以获取相同的 {category: count} 映射(值不变) |
completion_tokens | completion_tokens | 不变 |
total_cost | total_cost | 不变 |
total_tokens | total_tokens | 不变 |
reference_dataset_id | reference_dataset_id | 不变 |
reference_example_id | reference_example_id | 不变 |
tags | tags | 不变 |
thread_id | thread_id | 不变 |
session_id | project_id | 已重命名 |
in_dataset | is_in_dataset | 已重命名 |
child_run_ids | (已移除) | 无对应项 |
direct_child_run_ids | (已移除) | 无对应项 |
execution_order | (已移除) | 无对应项 |
inputs_s3_urls | (已移除) | 内部存储 URL;v2 中不暴露 |
last_queued_at | (已移除) | 无对应项 |
manifest_id | (已移除) | 使用 manifest |
manifest_s3_id | (已移除) | 内部存储 URL;v2 中不暴露 |
messages | (已移除) | 无对应项 |
outputs_s3_urls | (已移除) | 内部存储 URL;v2 中不暴露 |
parent_run_id | (已移除) | 使用 parent_run_ids |
s3_urls | (已移除) | 内部存储 URL;v2 中不暴露 |
serialized | (已移除) | 使用 manifest |
share_token | (已移除) | 使用 share_url |
trace_first_received_at | (已移除) | 无对应项 |
trace_max_start_time | (已移除) | 无对应项 |
trace_min_start_time | (已移除) | 无对应项 |
trace_tier | (已移除) | 无对应项 |
trace_upgrade | (已移除) | 无对应项 |
ttl_seconds | (已移除) | 无对应项 |
| (不可用) | attachments | 新增:将附件文件名映射到预签名下载 URL |
| (不可用) | error_preview | 新增:截断的错误片段 |
| (不可用) | is_root | 新增 |
| (不可用) | latency_seconds | 新增:以秒为单位的时钟持续时间 |
| (不可用) | manifest | 新增:完整的清单对象(替代 serialized 和 manifest_id) |
| (不可用) | metadata | 新增:之前嵌套在 extra.metadata 下 |
| (不可用) | share_url | 新增:公开分享 URL(仅在运行已分享时设置) |
| (不可用) | thread_evaluation_time | 新增 |
示例
通过 ID 获取单个运行
- Python
- TypeScript
- Java
- Go
- cURL
runs.retrieve 需要一个额外的 project_id(UUID)参数,这是 read_run 不需要的。它还接受一个可选的 start_time——提供该参数可以加快检索速度,但并非必需。请先通过 client.aread_project() 解析项目 UUID。- Before
- After
Before
from langsmith import Client
client = Client()
run_id = "<run-id>"
run = client.read_run(run_id)
After
import asyncio
from langsmith import Client
async def main():
client = Client()
project = await client.aread_project(project_name="default")
run_id = "<run-id>"
start_time = "2026-06-01T12:00:00Z" # 可选,但能加快检索速度
run = await client.runs.retrieve(
run_id=run_id,
project_id=str(project.id),
start_time=start_time,
)
asyncio.run(main())
client.runs.retrieve 需要一个额外的 project_id(UUID)参数,这是 readRun 不需要的。它还接受一个可选的 start_time——提供该参数可以加快检索速度,但并非必需。请先通过 client.readProject() 解析项目 UUID。- Before
- After
retrieveV2() 需要一个额外的 projectId()(UUID)参数,这是 client.runs().retrieve() 不需要的。它还接受一个可选的 startTime()——提供该参数可以加快检索速度,但并非必需。请先通过 client.sessions().list() 解析项目 UUID。- Before
- After
GetV2() 需要一个额外的 ProjectID(UUID)参数,这是 client.Runs.Get() 不需要的。它还接受一个可选的 StartTime——提供该参数可以加快检索速度,但并非必需。请先通过 client.Sessions.List() 解析项目 UUID。- Before
- After
GET /api/v2/runs/{run_id} 需要一个额外的 project_id(UUID)查询参数,这是 GET /api/v1/runs/{run_id} 不需要的。它还接受一个可选的 start_time——提供该参数可以加快检索速度,但并非必需。请先通过 GET /api/v1/sessions 请求解析项目 UUID。- Before
- After
RUN_ID="<run-id>"
curl "https://api.smith.langchain.com/api/v1/runs/$RUN_ID" \
-H "x-api-key: $LANGSMITH_API_KEY"
选择字段
- Python
- TypeScript
- Java
- Go
- cURL
read_run 返回完整的运行对象,无需选择。runs.retrieve 默认仅返回 id——传递 selects=[...] 以请求更多字段。- Before
- After
Before
from langsmith import Client
client = Client()
run_id = "<run-id>"
run = client.read_run(run_id=run_id)
print(run.name, run.status, run.total_tokens)
After
import asyncio
from langsmith import Client
async def main():
client = Client()
project = await client.aread_project(project_name="default")
run_id = "<run-id>"
start_time = "2026-06-01T12:00:00Z" # 可选,但能加快检索速度
run = await client.runs.retrieve(
run_id=run_id,
project_id=str(project.id),
start_time=start_time,
selects=["NAME", "STATUS", "TOTAL_TOKENS"],
)
print(run.name, run.status, run.total_tokens)
asyncio.run(main())
readRun 返回完整的运行对象,无需选择。client.runs.retrieve 默认仅返回 id——传递 selects: [...] 以请求更多字段。- Before
- After
.retrieve() 返回完整的运行对象,无需选择。.retrieveV2() 默认仅返回 id——对每个需要的字段调用 .addSelect(...)。- Before
- After
Get 返回完整的运行结构体,无需选择。GetV2 默认仅返回 ID——传递包含所需字段的 Selects。- Before
- After
GET /api/v1/runs/{run_id} 返回完整的运行对象,无需选择。GET /api/v2/runs/{run_id} 默认仅返回 id——为所需字段传递 selects 查询参数。- Before
- After
RUN_ID="<run-id>"
curl "https://api.smith.langchain.com/api/v1/runs/$RUN_ID" \
-H "x-api-key: $LANGSMITH_API_KEY"
处理未找到的运行
- Python
- TypeScript
- Java
- Go
- cURL
read_run 对于缺失的运行会从 langsmith.utils 抛出 LangSmithNotFoundError。runs.retrieve 现在从 langsmith 抛出 NotFoundError。- Before
- After
client.runs.retrieve 对于缺失的运行会抛出 NotFoundError。- Before
- After
.retrieve() 和 .retrieveV2() 都会抛出 com.langchain.smith.errors.NotFoundException——这没有变化,因为 Java SDK 在 SmithDB 之前就已经是 Stainless 生成的了。- Before
- After
Get 和 GetV2 都会返回一个可以用 errors.As 检查的 *langsmith.Error——这没有变化,因为 Go SDK 在 SmithDB 之前就已经是 Stainless 生成的了。检查 StatusCode 是否为 404。- Before
- After
GET /api/v1/runs/{run_id} 和 GET /api/v2/runs/{run_id} 对于缺失的运行都会返回 HTTP 404。请检查响应状态码。- Before
- After
加载运行的子运行
load_child_runs 标志和嵌套的 child_runs 字段已被移除。使用 traces.list_runs 获取追踪中的所有运行,然后按 parent_run_ids 进行过滤,该字段包含每个运行的完整祖先链,根节点在前,最近的父节点在后。
- Python
- TypeScript
- Java
- Go
- cURL
将
read_run(run_id, load_child_runs=True) 替换为 client.traces.list_runs。- Before
- After
将
loadChildRuns 选项替换为 client.traces.listRuns。- Before
- After
无需迁移:Java SDK 从不通过单次调用加载子运行,因此请使用
client.traces().listRuns() 来遍历追踪中的运行。无需迁移:Go SDK 从不通过单次调用加载子运行,因此请使用
client.Traces.ListRuns() 来遍历追踪中的运行。无需迁移:
GET /api/v1/runs/{run_id} 从不返回子运行,因此请使用 GET /api/v2/traces/{trace_id}/runs 来遍历追踪中的运行。Runs:获取 URL
获取运行的 LangSmith UI URL。主要变更
方法名称
- Python
- TypeScript
- Java
- Go
- cURL
参数
- Python
- TypeScript
- Java
- Go
- cURL
runs.get_url 需要直接传入运行的 project_id 和 trace_id,而不是从一个 run 对象或 project_name/project_id 回退中解析它们。旧版 (get_run_url) | 新版 (runs.get_url) | 备注 |
|---|---|---|
run (RunBase) | (已移除) | 不需要完整的 run 对象;请分别传递其标识字段 |
project_name | (已移除) | 无等效项;如果只有项目名称,请自行解析项目 UUID |
project_id | project_id | 必填;仍然是项目(会话)UUID |
| (无此参数) | run_id | 必填(位置参数);运行的 ID,之前从 run.id 读取 |
| (无此参数) | trace_id | 必填;运行的 trace UUID,之前在内部从 run 读取 |
| (无此参数) | start_time | 可选;运行的开始时间(RFC3339 格式);如果未知可省略 |
client.runs.getURL 需要直接传入运行的 project_id 和 trace_id,而不是从一个 run 对象或 runId 回退中解析它们。旧版 (getRunUrl) | 新版 (getURL) | 备注 |
|---|---|---|
run (Run) | (已移除) | 不需要完整的 run 对象;请分别传递其标识字段 |
runId | runID (位置参数) | 用途不变;现在是第一个位置参数而非命名选项 |
projectOpts | (已移除) | 无等效项;请自行解析项目 UUID |
| (无此参数) | project_id | 必填;snake_case 风格;项目(会话)UUID |
| (无此参数) | trace_id | 必填;snake_case 风格;运行的 trace UUID |
| (无此参数) | start_time | 可选;snake_case 风格;运行的开始时间(RFC3339 格式);如果未知可省略 |
| 旧版 | 新版 (RunGetUrlParams) | 备注 |
|---|---|---|
| (无旧版方法) | runId | 必填(位置参数);运行的 ID |
| (无旧版方法) | projectId() | 必填;项目(会话)UUID |
| (无旧版方法) | traceId() | 必填;运行的 trace UUID |
| (无旧版方法) | startTime() | 可选;运行的开始时间(RFC3339 格式);如果未知可省略 |
| 旧版 | 新版 (RunGetURLParams) | 备注 |
|---|---|---|
| (无旧版方法) | runID (位置参数) | 必填;运行的 ID |
| (无旧版方法) | ProjectID | 必填;项目(会话)UUID |
| (无旧版方法) | TraceID | 必填;运行的 trace UUID |
| (无旧版方法) | StartTime | 可选;运行的开始时间(RFC3339 格式);如果未知可省略 |
| 旧版 | 新版 (GET /api/v2/runs/{run_id}/url) | 备注 |
|---|---|---|
| (无旧版端点) | run_id (路径参数) | 必填 |
| (无旧版端点) | project_id (查询参数) | 必填;项目(会话)UUID |
| (无旧版端点) | trace_id (查询参数) | 必填;运行的 trace UUID |
| (无旧版端点) | start_time (查询参数) | 可选;运行的开始时间(RFC3339 格式);如果未知可省略 |
响应
- Python
- TypeScript
- Java
- Go
- cURL
| 旧版 | 新版 | 备注 |
|---|---|---|
str (URL 字符串) | RunGetURLResponse.url | 响应现在被包装在一个对象中;读取 .url 属性 |
| 旧版 | 新版 | 备注 |
|---|---|---|
string (URL 字符串) | RunGetURLResponse.url | 响应现在被包装在一个对象中;读取 .url 属性 |
| 旧版 | 新版 | 备注 |
|---|---|---|
| (无旧版方法) | RunGetUrlResponse.url() | 返回 Optional<String> |
| 旧版 | 新版 | 备注 |
|---|---|---|
| (无旧版方法) | RunGetURLResponse.URL | 返回一个 string |
| 旧版 | 新版 | 备注 |
|---|---|---|
| (无旧版端点) | {"url": "..."} | 包含单个 url 字段的 JSON 对象 |
示例
获取运行的 URL
- Python
- TypeScript
- Java
- Go
- cURL
get_run_url 接受一个完整的 run 对象。runs.get_url 是异步的,需要分别传入运行的 project_id(在旧版 v1 架构中为其 session_id)和 trace_id,start_time 可选。- 迁移前
- 迁移后
getRunUrl 接受一个完整的 run 对象。runs.getURL 需要分别传入运行的 project_id(在旧版 v1 架构中为其 session_id)和 trace_id,start_time 可选。- 迁移前
- 迁移后
Java SDK 没有旧版等效方法。
runs().getUrl 需要运行的 projectId() 和 traceId(),startTime() 可选。Go SDK 没有旧版等效方法。
Runs.GetURL 需要运行的 ProjectID 和 TraceID,StartTime 可选。REST API 没有旧版等效端点。
GET /api/v2/runs/{run_id}/url 需要运行的 project_id 和 trace_id 查询参数,start_time 可选。追踪:查询
返回单个追踪项目中的追踪列表(根运行)。每个条目包含追踪的根运行以及可选的追踪级聚合数据(total_tokens、total_cost、first_token_time),这些聚合数据位于 trace_aggregates 下,因此客户端永远不需要根据 trace_id 进行合并。
追踪扫描在 start_time 窗口内进行:min_start_time 默认为请求前24小时,max_start_time 默认为请求时间。可显式设置任一参数以扩大或缩小窗口。
支持过滤器(trace_filter、tree_filter)和字段投影(selects)。
主要变更
方法名称
- Python
- TypeScript
- Java
- Go
- cURL
| 变更前 | 变更后 |
|---|---|
client.list_runs(is_root=True) (通用方法) | client.traces.query() |
client.traces.query() 现在是异步的。调用时需要使用 await。| 变更前 | 变更后 |
|---|---|
client.listRuns({ isRoot: true }) (通用方法) | client.traces.query() |
| 变更前 | 变更后 |
|---|---|
client.runs().query() (通用方法,使用 isRoot(true)) | client.traces().query() |
| 变更前 | 变更后 |
|---|---|
client.Runs.Query() (通用方法,使用 IsRoot: true) | client.Traces.Query() |
| 变更前 | 变更后 |
|---|---|
POST /api/v1/runs/query (参数 is_root=true) | POST /api/v2/traces/query |
查询参数
- Python
- TypeScript
- Java
- Go
- cURL
session(项目 UUID 列表)变为project_id(单个 UUID);traces.query每次调用严格限定于一个项目。is_root参数被移除:traces.query在隐式情况下总是限定于根运行。- 通用的
filter(用于对任何运行进行评估)没有直接对应项;请改用trace_filter或tree_filter。 trace_filter和tree_filter保持不变;它们已在list_runs方法中存在。trace_ids是新增参数:一条快速路径限制,用于限制到已知的追踪 UUID 集合,在大规模情况下比等效的trace_filter更高效。start_time(无默认值)变为min_start_time,省略时默认为24小时前。max_start_time是新增参数,默认为请求时间;list_runs的end_time是根据运行自身的结束时间戳进行过滤,而不是扫描窗口的边界。select重命名为selects;条目会路由到trace_aggregates(total_tokens、total_cost、first_token_time)或root_run(所有其他字段)。
session(项目 UUID 列表)变为project_id(单个 UUID);traces.query每次调用严格限定于一个项目。isRoot参数被移除:traces.query在隐式情况下总是限定于根运行。- 通用的
filter(用于对任何运行进行评估)没有直接对应项;请改用trace_filter或tree_filter。 traceFilter和treeFilter作为trace_filter/tree_filter保持不变;它们已在listRuns方法中存在。注意 v1 方法采用驼峰式选项(traceFilter);v2 资源方法直接采用传输格式的snake_case键名。trace_ids是新增参数:一条快速路径限制,用于限制到已知的追踪 UUID 集合,在大规模情况下比等效的trace_filter更高效。startTime(无默认值)变为min_start_time,省略时默认为24小时前。max_start_time是新增参数,默认为请求时间;listRuns的endTime是根据运行自身的结束时间戳进行过滤,而不是扫描窗口的边界。select重命名为selects;条目会路由到trace_aggregates(total_tokens、total_cost、first_token_time)或root_run(所有其他字段)。
session(项目 UUID 的List<String>)变为projectId(单个 UUID);traces().query()每次调用严格限定于一个项目。isRoot参数被移除:traces().query()在隐式情况下总是限定于根运行。- 通用的
filter(用于对任何运行进行评估)没有直接对应项;请改用traceFilter或treeFilter。 traceFilter和treeFilter保持不变;它们已在RunQueryParams中存在。traceIds是新增参数:一条快速路径限制,用于限制到已知的追踪 UUID 集合,在大规模情况下比等效的traceFilter更高效。startTime(无默认值)变为minStartTime,省略时默认为24小时前。maxStartTime是新增参数,默认为请求时间;RunQueryParams的endTime是根据运行自身的结束时间戳进行过滤,而不是扫描窗口的边界。select重命名为selects;条目会路由到traceAggregates(totalTokens、totalCost、firstTokenTime)或rootRun(所有其他字段)。
Session(项目 UUID 的[]string)变为ProjectID(单个 UUID);Traces.Query()每次调用严格限定于一个项目。IsRoot参数被移除:Traces.Query()在隐式情况下总是限定于根运行。- 通用的
Filter(用于对任何运行进行评估)没有直接对应项;请改用TraceFilter或TreeFilter。 TraceFilter和TreeFilter保持不变;它们已在RunQueryParams中存在。TraceIDs是新增参数:一条快速路径限制,用于限制到已知的追踪 UUID 集合,在大规模情况下比等效的TraceFilter更高效。StartTime(无默认值)变为MinStartTime,省略时默认为24小时前。MaxStartTime是新增参数,默认为请求时间;RunQueryParams的EndTime是根据运行自身的结束时间戳进行过滤,而不是扫描窗口的边界。Select重命名为Selects;条目会路由到TraceAggregates(TotalTokens、TotalCost、FirstTokenTime)或RootRun(所有其他字段)。
session(项目 UUID 列表)变为project_id(单个 UUID)。is_root参数被移除:该端点在隐式情况下总是限定于根运行。- 通用的
filter没有直接对应项;请改用trace_filter或tree_filter。两者均已存在于POST /api/v1/runs/query中。 trace_ids是新增参数:一条快速路径限制,用于限制到已知的追踪 UUID 集合。start_time(无默认值)变为min_start_time,省略时默认为24小时前。max_start_time是新增参数,默认为请求时间。select重命名为selects。
响应字段
- Python
- TypeScript
- Java
- Go
- cURL
root_run携带与“运行:查询”相同的Run结构(id、name、run_type、status等),由selects控制。total_tokens/total_cost从root_run移动到trace_aggregates,它们是追踪中所有运行的总和,而不仅仅是根运行。当没有选择聚合字段时,响应中将完全省略trace_aggregates。trace_aggregates.first_token_time是新增字段。
root_run携带与“运行:查询”相同的Run结构(id、name、run_type、status等),由selects控制。total_tokens/total_cost从root_run移动到trace_aggregates,它们是追踪中所有运行的总和,而不仅仅是根运行。当没有选择聚合字段时,响应中将完全省略trace_aggregates。trace_aggregates.first_token_time是新增字段。
rootRun()携带与“运行:查询”相同的RunSchema结构(totalTokens()、name()、runType()、status()等),由selects控制。totalTokens()/totalCost()从rootRun()移动到traceAggregates(),它们是追踪中所有运行的总和,而不仅仅是根运行。traceAggregates().firstTokenTime()是新增字段。
RootRun携带与“运行:查询”相同的Run结构,由Selects控制。TotalTokens/TotalCost从RootRun移动到TraceAggregates,它们是追踪中所有运行的总和,而不仅仅是根运行。检查TraceAggregates是否不存在可通过trace.TraceAggregates.JSON.RawJSON() == "",因为它是一个值类型,而不是指针。TraceAggregates.FirstTokenTime是新增字段。
JSON 响应字段使用
snake_case,与下面的要点匹配。root_run携带与“运行:查询”相同的结构,由selects控制。total_tokens/total_cost从root_run移动到trace_aggregates,它们是追踪中所有运行的总和,而不仅仅是根运行。trace_aggregates.first_token_time是新增字段。
示例
列出追踪(根运行)
获取项目中的每个追踪(根运行),替代list_runs(is_root=True)。
- Python
- TypeScript
- Java
- Go
- cURL
- Before
- After
Before
from langsmith import Client
client = Client()
project = client.read_project(project_name="default")
root_runs = list(client.list_runs(project_id=project.id, is_root=True, limit=5))
for root_run in root_runs:
print(root_run.trace_id, root_run.name)
After
import asyncio
from langsmith import Client
async def main():
client = Client()
project = await client.aread_project(project_name="default")
count = 0
async for trace in client.traces.query(
project_id=str(project.id),
min_start_time="2026-07-01T00:00:00Z",
max_start_time="2026-07-31T23:59:59Z",
selects=["NAME"],
):
print(trace.root_run.trace_id, trace.root_run.name)
count += 1
if count >= 5:
break
asyncio.run(main())
- Before
- After
Before
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
for await (const run of client.listRuns({ projectId: project.id, isRoot: true, limit: 5 })) {
console.log(run.trace_id, run.name);
}
After
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
let count = 0;
for await (const trace of client.traces.query({
project_id: project.id,
min_start_time: "2026-07-01T00:00:00Z",
max_start_time: "2026-07-31T23:59:59Z",
selects: ["NAME"],
})) {
console.log(trace.root_run?.trace_id, trace.root_run?.name);
count += 1;
if (count >= 5) break;
}
- Before
- After
之前
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.runs.RunQueryParams
import com.langchain.smith.models.sessions.SessionListParams
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
val rootRuns = client.runs().query(
RunQueryParams.builder()
.addSession(project.id())
.isRoot(true)
.limit(5L)
.build()
).runs()
for (run in rootRuns) {
println("${run.traceId()} ${run.name()}")
}
After
import java.time.OffsetDateTime
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.runs.RunSelectField
import com.langchain.smith.models.sessions.SessionListParams
import com.langchain.smith.models.traces.TraceQueryParams
import kotlin.jvm.optionals.getOrNull
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
val traces = client.traces().query(
TraceQueryParams.builder()
.projectId(project.id())
.minStartTime(OffsetDateTime.parse("2026-07-01T00:00:00Z"))
.maxStartTime(OffsetDateTime.parse("2026-07-31T23:59:59Z"))
.addSelect(RunSelectField.NAME)
.build()
).items().take(5)
for (trace in traces) {
println("${trace.rootRun().get().traceId().getOrNull()} ${trace.rootRun().get().name().getOrNull()}")
}
- Before
- After
Before
package main
import (
"context"
"fmt"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("default"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
rootRuns, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
Session: langsmith.F([]string{projectID}),
IsRoot: langsmith.F(true),
Limit: langsmith.F(int64(5)),
})
if err != nil {
panic(err.Error())
}
for _, run := range rootRuns.Runs {
fmt.Println(run.TraceID, run.Name)
}
}
After
package main
import (
"context"
"fmt"
"time"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("default"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
minStart, _ := time.Parse(time.RFC3339, "2026-07-01T00:00:00Z")
maxStart, _ := time.Parse(time.RFC3339, "2026-07-31T23:59:59Z")
iter := client.Traces.QueryAutoPaging(ctx, langsmith.TraceQueryParams{
ProjectID: langsmith.F(projectID),
MinStartTime: langsmith.F(minStart),
MaxStartTime: langsmith.F(maxStart),
Selects: langsmith.F([]langsmith.RunSelectField{langsmith.RunSelectFieldName}),
})
count := 0
for iter.Next() {
trace := iter.Current()
fmt.Println(trace.RootRun.TraceID, trace.RootRun.Name)
count++
if count >= 5 {
break
}
}
if err := iter.Err(); err != nil {
panic(err.Error())
}
}
- Before
- After
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
curl -s -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg pid "$PROJECT_ID" '{"session": [$pid], "is_root": true, "limit": 5}')" \
| jq '(.runs // []) | map({trace_id: .trace_id, name: .name})'
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
curl -X POST "https://api.smith.langchain.com/api/v2/traces/query" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg pid "$PROJECT_ID" '{
"project_id": $pid,
"min_start_time": "2026-07-01T00:00:00Z",
"max_start_time": "2026-07-31T23:59:59Z",
"page_size": 5,
"selects": ["NAME"]
}')" | jq '.items | map({trace_id: .root_run.trace_id, name: .root_run.name})'
获取追踪的总令牌数和成本
从trace_aggregates 而不是根运行中读取追踪的令牌和成本总数,v1 版本是将它们保存在根运行中的。
- Python
- TypeScript
- Java
- Go
- cURL
- Before
- After
Before
from langsmith import Client
client = Client()
project = client.read_project(project_name="default")
root_runs = list(client.list_runs(project_id=project.id, is_root=True, limit=5))
for root_run in root_runs:
print(root_run.trace_id, root_run.total_tokens, root_run.total_cost)
After
import asyncio
from langsmith import Client
async def main():
client = Client()
project = await client.aread_project(project_name="默认")
count = 0
async for trace in client.traces.query(
project_id=str(project.id),
min_start_time="2026-07-01T00:00:00Z",
max_start_time="2026-07-31T23:59:59Z",
selects=["NAME", "TOTAL_TOKENS", "TOTAL_COST"],
):
count += 1
if trace.trace_aggregates is not None:
print(
trace.root_run.name,
trace.trace_aggregates.total_tokens,
trace.trace_aggregates.total_cost,
)
if count >= 5:
break
asyncio.run(main())
- Before
- After
Before
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
for await (const rootRun of client.listRuns({ projectId: project.id, isRoot: true, limit: 5 })) {
console.log(rootRun.trace_id, rootRun.total_tokens, rootRun.total_cost);
}
After
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
let count = 0;
for await (const trace of client.traces.query({
project_id: project.id,
min_start_time: "2026-07-01T00:00:00Z",
max_start_time: "2026-07-31T23:59:59Z",
selects: ["NAME", "TOTAL_TOKENS", "TOTAL_COST"],
})) {
count += 1;
if (trace.trace_aggregates) {
console.log(trace.root_run?.name, trace.trace_aggregates.total_tokens, trace.trace_aggregates.total_cost);
}
if (count >= 5) break;
}
Before 示例仅读取
totalTokens。totalCost 被省略,因为在 v1 的 RunSchema 类型上读取它会触发当前 Java 绑定中一个已知的反序列化错误(它期望一个字符串,但 API 返回一个数字)。- Before
- After
Before
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.runs.RunQueryParams
import com.langchain.smith.models.sessions.SessionListParams
import kotlin.jvm.optionals.getOrNull
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
val rootRuns = client.runs().query(
RunQueryParams.builder()
.addSession(project.id())
.isRoot(true)
.limit(5L)
.build()
).runs()
// 这里省略了 totalCost() —— RunSchema.totalCost()
// 在 v1 Java 绑定中存在一个已知的反序列化缺陷。
for (rootRun in rootRuns) {
println("${rootRun.traceId()} ${rootRun.totalTokens().getOrNull()}")
}
After
import java.time.OffsetDateTime
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.runs.RunSelectField
import com.langchain.smith.models.sessions.SessionListParams
import com.langchain.smith.models.traces.TraceQueryParams
import kotlin.jvm.optionals.getOrNull
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
val traces = client.traces().query(
TraceQueryParams.builder()
.projectId(project.id())
.minStartTime(OffsetDateTime.parse("2026-07-01T00:00:00Z"))
.maxStartTime(OffsetDateTime.parse("2026-07-31T23:59:59Z"))
.addSelect(RunSelectField.NAME)
.addSelect(RunSelectField.TOTAL_TOKENS)
.addSelect(RunSelectField.TOTAL_COST)
.build()
).items()
var count = 0
for (trace in traces) {
count++
val aggregates = trace.traceAggregates().getOrNull()
if (aggregates != null) {
println("${trace.rootRun().get().name().getOrNull()} ${aggregates.totalTokens().getOrNull()} ${aggregates.totalCost().getOrNull()}")
}
if (count >= 5) break
}
- Before
- After
Before
package main
import (
"context"
"fmt"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("default"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
rootRuns, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
Session: langsmith.F([]string{projectID}),
IsRoot: langsmith.F(true),
Limit: langsmith.F(int64(5)),
})
if err != nil {
panic(err.Error())
}
for _, rootRun := range rootRuns.Runs {
fmt.Println(rootRun.TraceID, rootRun.TotalTokens, rootRun.TotalCost)
}
}
After
package main
import (
"context"
"fmt"
"time"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("default"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
minStart, _ := time.Parse(time.RFC3339, "2026-07-01T00:00:00Z")
maxStart, _ := time.Parse(time.RFC3339, "2026-07-31T23:59:59Z")
iter := client.Traces.QueryAutoPaging(ctx, langsmith.TraceQueryParams{
ProjectID: langsmith.F(projectID),
MinStartTime: langsmith.F(minStart),
MaxStartTime: langsmith.F(maxStart),
Selects: langsmith.F([]langsmith.RunSelectField{
langsmith.RunSelectFieldName,
langsmith.RunSelectFieldTotalTokens,
langsmith.RunSelectFieldTotalCost,
}),
})
count := 0
for iter.Next() {
trace := iter.Current()
count++
if trace.TraceAggregates.JSON.RawJSON() != "" {
fmt.Println(trace.RootRun.Name, trace.TraceAggregates.TotalTokens, trace.TraceAggregates.TotalCost)
}
if count >= 5 {
break
}
}
if err := iter.Err(); err != nil {
panic(err.Error())
}
}
- Before
- After
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
curl -s -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg pid "$PROJECT_ID" '{"session": [$pid], "is_root": true, "limit": 5}')" \
| jq '.runs[] | {trace_id, total_tokens, total_cost}'
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
curl -X POST "https://api.smith.langchain.com/api/v2/traces/query" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg pid "$PROJECT_ID" '{
"project_id": $pid,
"min_start_time": "2026-07-01T00:00:00Z",
"max_start_time": "2026-07-31T23:59:59Z",
"page_size": 5,
"selects": ["NAME", "TOTAL_TOKENS", "TOTAL_COST"]
}')"
按状态查找追踪,或按 ID 获取追踪
使用trace_filter 按状态(例如,出错)过滤追踪,或者跳过过滤,使用 trace_ids 直接更快地获取已知的追踪。
- Python
- TypeScript
- Java
- Go
- cURL
- Before
- After
Before
from langsmith import Client
client = Client()
project = client.read_project(project_name="default")
# v1 没有仅针对根运行的过滤概念 — is_root 加上常规过滤器是
# 最接近的等价物,仍然扫描每个运行以进行匹配。
error_traces = client.list_runs(
project_id=project.id,
is_root=True,
filter='eq(status, "error")',
limit=5,
)
for run in error_traces:
print(run.trace_id)
After
import asyncio
from langsmith import Client
async def main():
client = Client()
project = await client.aread_project(project_name="default")
# trace_filter 隐含仅针对根运行——无需指定 is_root。
count = 0
async for trace in client.traces.query(
project_id=str(project.id),
min_start_time="2026-07-01T00:00:00Z",
max_start_time="2026-07-31T23:59:59Z",
trace_filter='eq(status, "error")',
):
print(trace.root_run.trace_id)
count += 1
if count >= 5:
break
# 当你已经知道需要哪些追踪时,trace_ids 提供了一条快速路径。
trace_id = "<trace-id>"
async for trace in client.traces.query(
project_id=str(project.id),
min_start_time="2026-07-01T00:00:00Z",
max_start_time="2026-07-31T23:59:59Z",
trace_ids=[trace_id],
):
print(trace.root_run.trace_id)
asyncio.run(main())
- Before
- After
Before
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
// v1 版本没有根运行过滤概念——isRoot 加上常规过滤是最接近的等效方式,仍然需要扫描每个运行来匹配。
for await (const run of client.listRuns({
projectId: project.id,
isRoot: true,
filter: 'eq(status, "error")',
limit: 5,
})) {
console.log(run.trace_id);
}
After
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
// trace_filter 隐式地仅限根运行 —— 不需要指定 is_root。
let count = 0;
for await (const trace of client.traces.query({
project_id: project.id,
min_start_time: "2026-07-01T00:00:00Z",
max_start_time: "2026-07-31T23:59:59Z",
trace_filter: 'eq(status, "error")',
})) {
console.log(trace.root_run?.trace_id);
count += 1;
if (count >= 5) break;
}
// trace_ids 是当你已知需要哪些跟踪时的快速路径。
let traceId = "<trace-id>";
for await (const trace of client.traces.query({
project_id: project.id,
min_start_time: "2026-07-01T00:00:00Z",
max_start_time: "2026-07-31T23:59:59Z",
trace_ids: [traceId],
})) {
console.log(trace.root_run?.trace_id);
}
- Before
- After
Before
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.runs.RunQueryParams
import com.langchain.smith.models.sessions.SessionListParams
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
// v1 版本没有“仅根运行”过滤的概念——使用 isRoot 加上常规过滤是最接近的等效方式,但仍然需要扫描每个运行来进行匹配。
val runs = client.runs().query(
RunQueryParams.builder()
.addSession(project.id())
.isRoot(true)
.filter("eq(status, \"error\")")
.limit(5L)
.build()
).runs()
for (run in runs) {
println(run.traceId())
}
After
import java.time.OffsetDateTime
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.sessions.SessionListParams
import com.langchain.smith.models.traces.TraceQueryParams
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
val minStart = OffsetDateTime.parse("2026-07-01T00:00:00Z")
val maxStart = OffsetDateTime.parse("2026-07-31T23:59:59Z")
// trace_filter 默认是仅针对根运行的 —— 不需要 is_root 参数。
val errorTraces = client.traces().query(
TraceQueryParams.builder()
.projectId(project.id())
.minStartTime(minStart)
.maxStartTime(maxStart)
.traceFilter("eq(status, \"error\")")
.build()
).items().take(5)
for (trace in errorTraces) {
println(trace.rootRun().get().traceId().get())
}
// 当你已经知道要查询哪些跟踪时,使用 traceIds 是一种快速路径。
var traceId = "<trace-id>"
val knownTraces = client.traces().query(
TraceQueryParams.builder()
.projectId(project.id())
.minStartTime(minStart)
.maxStartTime(maxStart)
.traceIds(listOf(traceId))
.build()
).items()
for (trace in knownTraces) {
println(trace.rootRun().get().traceId().get())
}
- Before
- After
Before
package main
import (
"context"
"fmt"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("default"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
// v1版本没有仅限根运行的筛选器概念——IsRoot加上常规筛选器是最接近的等效方式,仍然需要扫描所有运行记录进行匹配。
runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
Session: langsmith.F([]string{projectID}),
IsRoot: langsmith.F(true),
Filter: langsmith.F(`eq(status, "error")`),
Limit: langsmith.F(int64(5)),
})
if err != nil {
panic(err.Error())
}
for _, run := range runs.Runs {
fmt.Println(run.TraceID)
}
}
After
package main
import (
"context"
"fmt"
"time"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("default"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
minStart, _ := time.Parse(time.RFC3339, "2026-07-01T00:00:00Z")
maxStart, _ := time.Parse(time.RFC3339, "2026-07-31T23:59:59Z")
// trace_filter 默认仅针对根运行(root-run),无需使用 is_root 参数。
iter := client.Traces.QueryAutoPaging(ctx, langsmith.TraceQueryParams{
ProjectID: langsmith.F(projectID),
MinStartTime: langsmith.F(minStart),
MaxStartTime: langsmith.F(maxStart),
TraceFilter: langsmith.F(`eq(status, "error")`),
})
count := 0
for iter.Next() {
trace := iter.Current()
fmt.Println(trace.RootRun.TraceID)
count++
if count >= 5 {
break
}
}
if err := iter.Err(); err != nil {
panic(err.Error())
}
// trace_ids 是一种快速查询方式,适用于已知所需追踪 ID 的情况。
traceID := "<trace-id>"
knownIter := client.Traces.QueryAutoPaging(ctx, langsmith.TraceQueryParams{
ProjectID: langsmith.F(projectID),
MinStartTime: langsmith.F(minStart),
MaxStartTime: langsmith.F(maxStart),
TraceIDs: langsmith.F([]string{traceID}),
})
for knownIter.Next() {
trace := knownIter.Current()
fmt.Println(trace.RootRun.TraceID)
}
if err := knownIter.Err(); err != nil {
panic(err.Error())
}
}
- Before
- After
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
# v1 has no root-run-only filter concept — is_root plus a regular filter is
# the closest equivalent, still scanning every run to match.
curl -s -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg pid "$PROJECT_ID" '{"session": [$pid], "is_root": true, "filter": "eq(status, \"error\")", "limit": 5}')" \
| jq '(.runs // []) | map(.trace_id)'
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
# trace_filter is implicitly root-run-only — no is_root needed.
curl -s -X POST "https://api.smith.langchain.com/api/v2/traces/query" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg pid "$PROJECT_ID" '{
"project_id": $pid,
"min_start_time": "2026-07-01T00:00:00Z",
"max_start_time": "2026-07-31T23:59:59Z",
"page_size": 5,
"trace_filter": "eq(status, \"error\")"
}')" | jq '.items | map(.root_run.trace_id)'
# trace_ids is a fast-path when you already know which traces you want.
TRACE_ID="<trace-id>"
curl -s -X POST "https://api.smith.langchain.com/api/v2/traces/query" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg pid "$PROJECT_ID" --arg tid "$TRACE_ID" '{
"project_id": $pid,
"min_start_time": "2026-07-01T00:00:00Z",
"max_start_time": "2026-07-31T23:59:59Z",
"trace_ids": [$tid]
}')" | jq '.items | map(.root_run.trace_id)'
追踪:列出运行记录
根据追踪ID,在最小/最大开始时间范围内返回运行记录。可选的filter;可重复的 selects 用于选择要返回的字段。
主要变更
方法名称
- Python
- TypeScript
- Java
- Go
- cURL
| 之前 | 之后 |
|---|---|
client.list_runs(trace_id=...) (通用方法) | client.traces.list_runs() |
client.traces.list_runs() 现在是异步的。调用时需使用 await。| 之前 | 之后 |
|---|---|
client.listRuns({ traceId }) (通用方法) | client.traces.listRuns() |
| 之前 | 之后 |
|---|---|
client.runs().query() (通用方法,使用 .trace(traceId)) | client.traces().listRuns() |
| 之前 | 之后 |
|---|---|
client.Runs.Query() (通用方法,使用 Trace: traceID) | client.Traces.ListRuns() |
| 之前 | 之后 |
|---|---|
POST /api/v1/runs/query (trace 字段) | GET /api/v2/traces/{trace_id}/runs |
查询参数
- Python
- TypeScript
- Java
- Go
- cURL
trace_id/trace从查询参数移至路径参数。project_id是新增的必填参数(SmithDB 分区键);list_runs(trace_id=...)不需要它。filter无变化。min_start_time/max_start_time是新增参数。与traces.query不同,它们都没有默认值:如果两者都省略,则完全不会按时间过滤运行记录。它们各自是可选的,但如果设置了其中一个,则必须同时传递另一个。select重命名为selects,使用与traces.query相同的 44 个值的枚举。
traceId/trace从查询参数移至路径参数。project_id是新增的必填参数(SmithDB 分区键);listRuns({ traceId })不需要它。filter无变化。min_start_time/max_start_time是新增参数。与traces.query不同,它们都没有默认值:如果两者都省略,则完全不会按时间过滤运行记录。它们各自是可选的,但如果设置了其中一个,则必须同时传递另一个。select重命名为selects,使用与traces.query相同的 44 个值的枚举。
traceId从查询参数 (.trace(traceId)) 移至位置路径参数。projectId是新增的必填参数(SmithDB 分区键);通用的runs().query()不需要它。filter无变化。minStartTime/maxStartTime是新增参数。与traces().query()不同,它们都没有默认值:如果两者都省略,则完全不会按时间过滤运行记录。它们各自是可选的,但如果设置了其中一个,则必须同时传递另一个。select重命名为selects(44 个值的枚举)。
traceID从查询参数 (Trace: traceID) 移至位置路径参数。ProjectID是新增的必填参数(SmithDB 分区键);通用的Runs.Query()不需要它。Filter无变化。MinStartTime/MaxStartTime是新增参数。与Traces.Query()不同,它们都没有默认值:如果两者都省略,则完全不会按时间过滤运行记录。它们各自是可选的,但如果设置了其中一个,则必须同时传递另一个。Select重命名为Selects。
trace从请求体字段移至路径段{trace_id}。project_id是新增的必填参数(SmithDB 分区键);POST /api/v1/runs/query不需要它。filter无变化。min_start_time/max_start_time是新增参数。与traces.query不同,它们都没有默认值:如果两者都省略,则完全不会按时间过滤运行记录。它们各自是可选的,但如果设置了其中一个,则必须同时传递另一个。select重命名为selects。
响应字段
- Python
- TypeScript
- Java
- Go
- cURL
响应包含一个
items 字段:一个按 start_time 排序的 Run 对象列表,结构与上面的 Runs: query 响应相同。响应包含一个
items 字段:一个按 start_time 排序的 Run 对象数组,结构与上面的 Runs: query 响应相同。响应包含一个
items() 方法,返回 Optional<List<Run>>:该追踪的运行记录,按 start_time 排序,结构与上面的 Runs: query 响应相同。响应包含一个
Items 字段,类型为 []Run:该追踪的运行记录,按 start_time 排序,结构与上面的 Runs: query 响应相同。JSON 响应包含一个
items 数组字段:该追踪的运行记录,按 start_time 排序,结构与上面的 Runs: query 响应相同。示例
列出追踪中的所有运行记录
根据追踪ID,获取属于某个追踪的所有运行记录。- Python
- TypeScript
- Java
- Go
- cURL
- 之前
- 之后
Before
from langsmith import Client
client = Client()
project = client.read_project(project_name="default")
trace_id = "<trace-id>"
runs = list(client.list_runs(project_id=project.id, trace_id=trace_id))
for run in runs:
print(run.name, run.run_type, run.status)
After
import asyncio
from langsmith import Client
async def main():
# 创建 LangSmith 客户端实例
client = Client()
# 获取默认项目信息
project = await client.aread_project(project_name="default")
trace_id = "<trace-id>"
# 查询指定追踪 ID 的运行记录,选择特定字段
response = await client.traces.list_runs(
trace_id,
project_id=str(project.id),
selects=["NAME", "RUN_TYPE", "STATUS"],
)
# 遍历并打印每条运行记录的名称、类型和状态
for run in response.items:
print(run.name, run.run_type, run.status)
asyncio.run(main())
- 之前
- 之后
Before
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
let traceId = "<trace-id>";
const runs = [];
for await (const run of client.listRuns({ projectId: project.id, traceId })) {
runs.push(run);
}
for (const run of runs) {
console.log(run.name, run.run_type, run.status);
}
After
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
let traceId = "<trace-id>";
const response = await client.traces.listRuns(traceId, {
project_id: project.id,
selects: ["NAME", "RUN_TYPE", "STATUS"],
});
for (const run of response.items ?? []) {
console.log(run.name, run.run_type, run.status);
}
- 之前
- 之后
Before
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.runs.RunQueryParams
import com.langchain.smith.models.sessions.SessionListParams
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
var traceId = "<trace-id>"
val runs = client.runs().query(
RunQueryParams.builder()
.addSession(project.id())
.trace(traceId)
.build()
).runs()
for (run in runs) {
println("${run.name()} ${run.runType()} ${run.status()}")
}
After
import java.time.OffsetDateTime
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.sessions.SessionListParams
import com.langchain.smith.models.traces.TraceListRunsParams
import com.langchain.smith.models.traces.TraceQueryParams
import kotlin.jvm.optionals.getOrNull
// 初始化 Langsmith 客户端
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
// 获取名为 "default" 的第一个项目
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
// 替换为实际的 trace ID
var traceId = "<trace-id>"
// 列出该 trace 下的所有运行记录,并选择显示名称、运行类型和状态
val response = client.traces().listRuns(
traceId,
TraceListRunsParams.builder()
.projectId(project.id())
.addSelect(TraceListRunsParams.Select.NAME)
.addSelect(TraceListRunsParams.Select.RUN_TYPE)
.addSelect(TraceListRunsParams.Select.STATUS)
.build()
)
// 遍历并打印每个运行记录的名称、类型和状态
for (run in response.items().getOrNull() ?: emptyList()) {
println("${run.name().getOrNull()} ${run.runType().getOrNull()} ${run.status().getOrNull()}")
}
- 之前
- 之后
Before
package main
import (
"context"
"fmt"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("default"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
traceID := "<trace-id>"
runs, err := client.Runs.Query(ctx, langsmith.RunQueryParams{
Session: langsmith.F([]string{projectID}),
Trace: langsmith.F(traceID),
})
if err != nil {
panic(err.Error())
}
for _, run := range runs.Runs {
fmt.Println(run.Name, run.RunType, run.Status)
}
}
After
package main
import (
"context"
"fmt"
"time"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("默认"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
traceID := "<trace-id>"
response, err := client.Traces.ListRuns(ctx, traceID, langsmith.TraceListRunsParams{
ProjectID: langsmith.F(projectID),
Selects: langsmith.F([]langsmith.TraceListRunsParamsSelect{
langsmith.TraceListRunsParamsSelectName,
langsmith.TraceListRunsParamsSelectRunType,
langsmith.TraceListRunsParamsSelectStatus,
}),
})
if err != nil {
panic(err.Error())
}
for _, run := range response.Items {
fmt.Println(run.Name, run.RunType, run.Status)
}
}
- 之前
- 之后
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
TRACE_ID="<trace-id>"
curl -s -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg pid "$PROJECT_ID" --arg tid "$TRACE_ID" '{"session": [$pid], "trace": $tid}')" \
| jq '.runs // []'
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
TRACE_ID="<trace-id>"
curl -G "https://api.smith.langchain.com/api/v2/traces/$TRACE_ID/runs" \
-H "x-api-key: $LANGSMITH_API_KEY" \
--data-urlencode "project_id=$PROJECT_ID" \
--data-urlencode "selects=NAME" \
--data-urlencode "selects=RUN_TYPE" \
--data-urlencode "selects=STATUS"
仅获取追踪中的LLM调用
将追踪的运行记录范围缩小到特定的运行类型,例如仅LLM调用。- Python
- TypeScript
- Java
- Go
- cURL
- 之前
- 之后
Before
from langsmith import Client
client = Client()
project = client.read_project(project_name="default")
trace_id = "<trace-id>"
llm_runs = list(
client.list_runs(
project_id=project.id,
trace_id=trace_id,
filter='eq(run_type, "llm")',
)
)
import asyncio
from langsmith import Client
async def main():
client = Client()
project = await client.aread_project(project_name="default")
trace_id = "<trace-id>"
response = await client.traces.list_runs(
trace_id,
project_id=str(project.id),
filter='eq(run_type, "llm")',
selects=["NAME", "STATUS"],
)
llm_runs = response.items
asyncio.run(main())
- 之前
- 之后
Before
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
let traceId = "<trace-id>";
const llmRuns = [];
for await (const run of client.listRuns({
projectId: project.id,
traceId,
filter: 'eq(run_type, "llm")',
})) {
llmRuns.push(run);
}
// 获取运行记录
After
import { Client } from "langsmith";
const client = new Client();
const project = await client.readProject({ projectName: "default" });
let traceId = "<trace-id>";
const response = await client.traces.listRuns(traceId, {
project_id: project.id,
filter: 'eq(run_type, "llm")',
selects: ["NAME", "STATUS"],
});
const llmRuns = response.items ?? [];
- 之前
- 之后
Before
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.runs.RunQueryParams
import com.langchain.smith.models.sessions.SessionListParams
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
var traceId = "<trace-id>"
client.runs().query(
RunQueryParams.builder()
.addSession(project.id())
.trace(traceId)
.filter("eq(run_type, \"llm\")")
.build()
).runs()
After
import java.time.OffsetDateTime
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.sessions.SessionListParams
import com.langchain.smith.models.traces.TraceListRunsParams
import com.langchain.smith.models.traces.TraceQueryParams
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val project = client.sessions().list(
SessionListParams.builder().name("default").limit(1L).build()
).items().first()
var traceId = "<trace-id>"
client.traces().listRuns(
traceId,
TraceListRunsParams.builder()
.projectId(project.id())
.filter("eq(run_type, \"llm\")")
.addSelect(TraceListRunsParams.Select.NAME)
.addSelect(TraceListRunsParams.Select.STATUS)
.build()
)
- 之前
- 之后
Before
package main
import (
"context"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("default"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
traceID := "<trace-id>"
_, err = client.Runs.Query(ctx, langsmith.RunQueryParams{
Session: langsmith.F([]string{projectID}),
Trace: langsmith.F(traceID),
Filter: langsmith.F(`eq(run_type, "llm")`),
})
if err != nil {
panic(err.Error())
}
}
After
package main
import (
"context"
"time"
"github.com/langchain-ai/langsmith-go"
)
func main() {
ctx := context.Background()
client := langsmith.NewClient()
sessions, err := client.Sessions.List(ctx, langsmith.SessionListParams{
Name: langsmith.F("default"),
Limit: langsmith.F(int64(1)),
})
if err != nil {
panic(err.Error())
}
projectID := sessions.Items[0].ID
traceID := "<trace-id>"
_, err = client.Traces.ListRuns(ctx, traceID, langsmith.TraceListRunsParams{
ProjectID: langsmith.F(projectID),
Filter: langsmith.F(`eq(run_type, "llm")`),
Selects: langsmith.F([]langsmith.TraceListRunsParamsSelect{
langsmith.TraceListRunsParamsSelectName,
langsmith.TraceListRunsParamsSelectStatus,
}),
})
if err != nil {
panic(err.Error())
}
}
- 之前
- 之后
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
TRACE_ID="<trace-id>"
curl -s -X POST "https://api.smith.langchain.com/api/v1/runs/query" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg pid "$PROJECT_ID" --arg tid "$TRACE_ID" '{"session": [$pid], "trace": $tid, "filter": "eq(run_type, \"llm\")"}')" \
| jq '.runs // []'
开始使用
阅读文档了解如何开始使用我们的产品。它提供了逐步指南、功能概述,以及 API、SDK 和工具的参考信息。
导航
目录
快速开始
以下是一个快速入门示例。请按照步骤创建并运行您的第一个应用。1
安装 CLI
首先,使用包管理器安装命令行工具:
- Tab Title
- Tab Title
- Tab Title
# 使用 npm 安装
npm install -g @company/cli
# 使用 yarn 安装
yarn global add @company/cli
# 使用 pnpm 安装
pnpm add -g @company/cli
2
3
启动开发服务器
进入项目目录并启动开发服务器:
# 进入项目目录
cd my-app
# 启动开发服务器
company-cli dev
安装
您可以通过多种方式将我们的库集成到您的项目中。系统要求
- Node.js:18.0 或更高版本
- 操作系统:macOS、Windows(包括 WSL)和 Linux
作为依赖项安装
# 使用 npm
npm install @company/core
# 使用 yarn
yarn add @company/core
# 使用 pnpm
pnpm add @company/core
配置
创建一个company.config.js 文件来配置您的项目。// company.config.js
module.exports = {
// 应用名称
name: '我的应用',
// 环境配置
env: {
development: {
apiUrl: 'http://localhost:8080'
},
production: {
apiUrl: 'https://api.example.com'
}
}
};
请确保将
node_modules 添加到您的 .gitignore 文件中,以避免将依赖项提交到版本控制。第一个项目
您的项目结构可能如下所示:my-app/
├── node_modules/
├── public/
├── src/
│ ├── components/
│ ├── pages/
│ ├── utils/
│ └── index.js
├── company.config.js
├── package.json
└── README.md
src/index.js:// src/index.js
import { init } from '@company/core';
// 初始化应用
const app = init({
// 配置选项
});
// 启动应用
app.start();
PROJECT_ID=$(curl -s "https://api.smith.langchain.com/api/v1/sessions?name=default&limit=1" \
-H "x-api-key: $LANGSMITH_API_KEY" | jq -r '.[0].id')
TRACE_ID="<trace-id>"
curl -G "https://api.smith.langchain.com/api/v2/traces/$TRACE_ID/runs" \
-H "x-api-key: $LANGSMITH_API_KEY" \
--data-urlencode "project_id=$PROJECT_ID" \
--data-urlencode "filter=eq(run_type, \"llm\")" \
--data-urlencode "selects=NAME" \
--data-urlencode "selects=STATUS"
import SmithdbThreadsQueryListAllBeforePy from '/snippets/code-samples/smithdb-migration/threads-query-list-all-before-py.mdx';
import SmithdbThreadsQueryListAllAfterPy from '/snippets/code-samples/smithdb-migration/threads-query-list-all-after-py.mdx';
import SmithdbThreadsQueryListAllBeforeJs from '/snippets/code-samples/smithdb-migration/threads-query-list-all-before-js.mdx';
import SmithdbThreadsQueryListAllAfterJs from '/snippets/code-samples/smithdb-migration/threads-query-list-all-after-js.mdx';
import SmithdbThreadsQueryListAllBeforeGo from '/snippets/code-samples/smithdb-migration/threads-query-list-all-before-go.mdx';
import SmithdbThreadsQueryListAllAfterGo from '/snippets/code-samples/smithdb-migration/threads-query-list-all-after-go.mdx';
import SmithdbThreadsQueryListAllBeforeKt from '/snippets/code-samples/smithdb-migration/threads-query-list-all-before-kt.mdx';
import SmithdbThreadsQueryListAllAfterKt from '/snippets/code-samples/smithdb-migration/threads-query-list-all-after-kt.mdx';
import SmithdbThreadsQueryListAllBeforeSh from '/snippets/code-samples/smithdb-migration/threads-query-list-all-before-sh.mdx';
import SmithdbThreadsQueryListAllAfterSh from '/snippets/code-samples/smithdb-migration/threads-query-list-all-after-sh.mdx';
import SmithdbThreadsQueryFilterStatusBeforePy from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-before-py.mdx';
import SmithdbThreadsQueryFilterStatusAfterPy from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-after-py.mdx';
import SmithdbThreadsQueryFilterStatusBeforeJs from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-before-js.mdx';
import SmithdbThreadsQueryFilterStatusAfterJs from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-after-js.mdx';
import SmithdbThreadsQueryFilterStatusBeforeGo from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-before-go.mdx';
import SmithdbThreadsQueryFilterStatusAfterGo from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-after-go.mdx';
import SmithdbThreadsQueryFilterStatusBeforeKt from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-before-kt.mdx';
import SmithdbThreadsQueryFilterStatusAfterKt from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-after-kt.mdx';
import SmithdbThreadsQueryFilterStatusBeforeSh from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-before-sh.mdx';
import SmithdbThreadsQueryFilterStatusAfterSh from '/snippets/code-samples/smithdb-migration/threads-query-filter-status-after-sh.mdx';
## 线程:查询
在项目中查询线程,支持基于游标的分页。返回匹配给定时间范围和可选筛选条件的线程。
### 主要变更
#### 方法名
<Tabs>
<Tab title="Python">
| 之前 | 之后 |
|--------|-------|
| `client.list_threads()` | `client.threads.query()` |
<Note>
`client.threads.query()` 现在是异步的。调用时需要使用 `await`。
</Note>
完整的参数和字段列表请参阅[参考文档](https://reference.langchain.com/python/langsmith/_openapi_client/resources/threads/ThreadsResource/query)。
</Tab>
<Tab title="TypeScript">
| 之前 | 之后 |
|--------|-------|
| `client.listThreads()` | `client.threads.query()` |
完整的参数和字段列表请参阅[参考文档](https://reference.langchain.com/javascript/langsmith/_openapi_client/Langsmith/Threads/query)。
</Tab>
<Tab title="Java">
<Note>Java 从未有过专门的线程列表方法。最接近的旧版等效方法是通用的运行查询,并按 `thread_id` 元数据约定在客户端手动分组。</Note>
| 之前 | 之后 |
|--------|-------|
| `client.runs().query()` (通用,客户端分组) | `client.threads().query()` |
完整的参数列表请参阅[参考文档](https://javadoc.io/doc/com.langchain.smith/langsmith-java/latest/com/langchain/smith/services/blocking/ThreadService.html)。
</Tab>
<Tab title="Go">
<Note>Go 从未有过专门的线程列表方法。最接近的旧版等效方法是通用的运行查询,并按 `thread_id` 元数据约定在客户端手动分组。</Note>
| 之前 | 之后 |
|--------|-------|
| `client.Runs.Query()` (通用,客户端分组) | `client.Threads.Query()` |
完整的参数列表请参阅[参考文档](https://pkg.go.dev/github.com/langchain-ai/langsmith-go#ThreadService.QueryAutoPaging)。
</Tab>
<Tab title="cURL">
| 之前 | 之后 |
|--------|-------|
| `POST /api/v1/runs/query` (`is_root=true`,客户端分组) | `POST /api/v2/threads/query` |
完整的参数和字段列表请参阅 [API 文档](/langsmith/smith-api/threads/query-threads)。
</Tab>
</Tabs>
#### 查询参数
<Tabs>
<Tab title="Python">
| 之前 (`list_threads`) | 之后 (`threads.query`) | 说明 |
|---|---|---|
| `project_id` 或 `project_name` | `project_id` | 新方法仅接受 UUID;如需按名称查找,请先通过 `aread_project()` 解析,模式与 `Runs: query` 相同 |
| `start_time`(默认为 1 天前) | `min_start_time` + `max_start_time` | 可选;默认为当前时间向前推 1 天的时间窗口,与 `start_time` 相同 |
| `offset` + `limit` | `cursor` + `page_size` | 偏移量分页已替换为游标分页 |
| `filter`(针对运行进行求值) | `filter` | 语法相同;现在针对每个线程的根运行进行求值 |
</Tab>
<Tab title="TypeScript">
| 之前 (`listThreads`) | 之后 (`threads.query`) | 说明 |
|---|---|---|
| `projectId` 或 `projectName` | `project_id` | 新方法仅接受 UUID;如需按名称查找,请先通过 `readProject()` 解析 |
| `startTime`(默认为 1 天前) | `min_start_time` + `max_start_time` | 可选;默认为当前时间向前推 1 天的时间窗口,与 `startTime` 相同 |
| `offset` + `limit` | `cursor` + `page_size` | 偏移量分页已替换为游标分页 |
| `filter` | `filter` | 语法相同;现在针对每个线程的根运行进行求值 |
</Tab>
<Tab title="Java">
没有需要映射的查询参数。没有专门的方法。旧方法使用通用的运行查询(`is_root=true`,按 `thread_id` 元数据手动分组)。`threads().query()` 接受 `projectId`、`minStartTime`、`maxStartTime`(两者均可选,默认为当前时间向前推 1 天的时间窗口)、`filter`、`pageSize`、`cursor`。
</Tab>
<Tab title="Go">
没有需要映射的查询参数。没有专门的方法。旧方法使用通用的运行查询(`IsRoot: true`,按 `thread_id` 元数据手动分组)。`Threads.Query()` 接受 `ProjectID`、`MinStartTime`、`MaxStartTime`(两者均可选,默认为当前时间向前推 1 天的时间窗口)、`Filter`、`PageSize`、`Cursor`。
</Tab>
<Tab title="cURL">
`POST /api/v2/threads/query` 的请求体字段:`project_id`、`min_start_time`(可选)、`max_start_time`(可选)、`filter`、`page_size`、`cursor`(均为 `snake_case` 命名)。`min_start_time`/`max_start_time` 省略时默认为当前时间向前推 1 天的时间窗口。
</Tab>
</Tabs>
#### 响应字段
<Tabs>
<Tab title="Python">
Python 旧版的 `ListThreadsItem` 仅有 `thread_id`、`runs`(完整的嵌入式 `Run[]`)、`count`、`min_start_time`、`max_start_time`。它完全没有 token/成本/延迟/反馈字段。
新的 `Thread` 永远不会嵌入完整的运行列表(那是 `threads.list_traces` 的用途),但添加了真实的 `feedback_stats`、`latency_p50`/`latency_p99`、带有每类 `_details` 的成本/token 总计、`first_trace_id`/`last_trace_id`、`first_inputs`/`last_outputs` 预览、`last_error`、`num_errored_turns`。
| 之前 (旧版 `ListThreadsItem`) | 之后 (新版 `Thread`) | 说明 |
|---|---|---|
| `thread_id` | `thread_id` | 不变 |
| `runs` (完整的嵌入式 `Run[]`) | *(不可用)* | 请使用 `threads.list_traces` 获取每个 trace 的详情 |
| `count` | `count` | 不变 |
| `min_start_time` | `min_start_time` | 不变 |
| `max_start_time` | `max_start_time` | 不变 |
| *(不可用)* | `start_time` | 新增:此行的参考起始时间,例如用于排序 |
| *(不可用)* | `trace_id` | 新增:一个代表性的根 trace UUID,例如用于深度链接 |
| *(不可用)* | `first_trace_id`, `last_trace_id` | 新增:查询窗口中时间最早/最晚的 trace UUID |
| *(不可用)* | `first_inputs`, `last_outputs` | 新增:来自第一个/最后一个 trace 的截断预览 |
| *(不可用)* | `last_error` | 新增 |
| *(不可用)* | `num_errored_turns` | 新增 |
| *(不可用)* | `latency_p50`, `latency_p99` | 新增 |
| *(不可用)* | `total_tokens`, `total_cost` | 新增 |
| *(不可用)* | `total_token_details`, `total_cost_details` | 新增:按类别划分的字典,与 `threads.list_traces` 不同,这些没有包装在 `.raw` 中 |
| *(不可用)* | `feedback_stats` | 新增 |
</Tab>
<Tab title="TypeScript">
| 之前 (旧版 `ListThreadsItem`) | 之后 (新版 `Thread`) | 说明 |
|---|---|---|
| `thread_id` | `thread_id` | 不变 |
| `runs` (完整的嵌入式 `Run[]`) | *(不可用)* | 请使用 `threads.listTraces` 获取每个 trace 的详情 |
| `count` | `count` | 不变 |
| `min_start_time` | `min_start_time` | 不变 |
| `max_start_time` | `max_start_time` | 不变 |
| `total_tokens` | `total_tokens` | 不变 |
| `total_cost` | `total_cost` | 不变 |
| `latency_p50`, `latency_p99` | `latency_p50`, `latency_p99` | 不变 |
| `feedback_stats` | `feedback_stats` | 不变 |
| `first_inputs`, `last_outputs` | `first_inputs`, `last_outputs` | 不变 |
| `last_error` | `last_error` | 不变 |
| *(不可用)* | `start_time` | 新增:此行的参考起始时间,例如用于排序 |
| *(不可用)* | `trace_id` | 新增:一个代表性的根 trace UUID,例如用于深度链接 |
| *(不可用)* | `first_trace_id`, `last_trace_id` | 新增:查询窗口中时间最早/最晚的 trace UUID |
| *(不可用)* | `num_errored_turns` | 新增 |
| *(不可用)* | `total_token_details`, `total_cost_details` | 新增:按类别划分的字典,与 `threads.listTraces` 不同,这些没有包装在 `.raw` 中 |
</Tab>
<Tab title="Java">
`Thread` 有 19 个字段:`threadId`、`count`、`feedbackStats`、`firstInputs`、`firstTraceId`、`lastError`、`lastOutputs`、`lastTraceId`、`latencyP50`、`latencyP99`、`maxStartTime`、`minStartTime`、`numErroredTurns`、`startTime`、`totalCost`、`totalCostDetails`、`totalTokenDetails`、`totalTokens`、`traceId`(均为 `Optional`)。
旧版 SDK 从未为此提供类型化响应。Java 最接近的等效方法是在客户端按 `thread_id` 元数据对原始 `runs().query()` 结果进行分组。下面列出的每个字段都是新增的。
| 新的 `Thread` 方法 | 说明 |
|---|---|
| `threadId()` | |
| `count()` | |
| `minStartTime()`, `maxStartTime()`, `startTime()` | |
| `firstTraceId()`, `lastTraceId()`, `traceId()` | 除了第一个/最后一个 trace UUID 外,`traceId()` 还是一个代表性的根 trace UUID,例如用于深度链接 |
| `firstInputs()`, `lastOutputs()` | 来自第一个/最后一个 trace 的截断预览 |
| `lastError()` | |
| `numErroredTurns()` | |
| `latencyP50()`, `latencyP99()` | |
| `totalTokens()`, `totalCost()` | |
| `totalTokenDetails()`, `totalCostDetails()` | 按类别划分的映射 |
| `feedbackStats()` | |
</Tab>
<Tab title="Go">
`Thread` 有 19 个字段,采用 Go 结构体的 `PascalCase` 形式(例如 `ThreadID`、`Count`、`LatencyP50`)。
旧版 SDK 从未为此提供类型化响应。Go 最接近的等效方法是在客户端按 `thread_id` 元数据对原始 `Runs.Query()` 结果进行分组。下面列出的每个字段都是新增的。
| 新的 `Thread` 字段 | 说明 |
|---|---|
| `ThreadID` | |
| `Count` | |
| `MinStartTime`, `MaxStartTime`, `StartTime` | |
| `FirstTraceID`, `LastTraceID`, `TraceID` | 除了第一个/最后一个 trace UUID 外,`TraceID` 还是一个代表性的根 trace UUID,例如用于深度链接 |
| `FirstInputs`, `LastOutputs` | 来自第一个/最后一个 trace 的截断预览 |
| `LastError` | |
| `NumErroredTurns` | |
| `LatencyP50`, `LatencyP99` | |
| `TotalTokens`, `TotalCost` | |
| `TotalTokenDetails`, `TotalCostDetails` | 按类别划分的映射 |
| `FeedbackStats` | |
</Tab>
<Tab title="cURL">
JSON 响应字段使用 `snake_case`:`thread_id`、`count`、`feedback_stats`、`first_inputs`、`first_trace_id`、`last_error`、`last_outputs`、`last_trace_id`、`latency_p50`、`latency_p99`、`max_start_time`、`min_start_time`、`num_errored_turns`、`start_time`、`total_cost`、`total_cost_details`、`total_token_details`、`total_tokens`、`trace_id`。
旧版 API 从未有过专门的线程端点。最接近的等效方法是 `POST /api/v1/runs/query`,并在客户端按 `thread_id` 元数据分组。下面列出的每个字段都是新增的。
| 新的 `threads.query` 响应字段 | 说明 |
|---|---|
| `thread_id` | |
| `count` | |
| `min_start_time`, `max_start_time`, `start_time` | |
| `first_trace_id`, `last_trace_id`, `trace_id` | 除了第一个/最后一个 trace UUID 外,`trace_id` 还是一个代表性的根 trace UUID,例如用于深度链接 |
| `first_inputs`, `last_outputs` | 来自第一个/最后一个 trace 的截断预览 |
| `last_error` | |
| `num_errored_turns` | |
| `latency_p50`, `latency_p99` | |
| `total_tokens`, `total_cost` | |
| `total_token_details`, `total_cost_details` | 按类别划分的字典 |
| `feedback_stats` | |
</Tab>
</Tabs>
### 示例
#### 列出项目中的线程
获取项目中在指定时间范围内有活动的每个线程。
<Tabs>
<Tab title="Python">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryListAllBeforePy />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryListAllAfterPy />
</Tab>
</Tabs>
</Tab>
<Tab title="TypeScript">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryListAllBeforeJs />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryListAllAfterJs />
</Tab>
</Tabs>
</Tab>
<Tab title="Java">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryListAllBeforeKt />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryListAllAfterKt />
</Tab>
</Tabs>
</Tab>
<Tab title="Go">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryListAllBeforeGo />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryListAllAfterGo />
</Tab>
</Tabs>
</Tab>
<Tab title="cURL">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryListAllBeforeSh />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryListAllAfterSh />
</Tab>
</Tabs>
</Tab>
</Tabs>
#### 查找有错误的线程
查找包含以错误结束的对话轮次的线程。
<Tabs>
<Tab title="Python">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryFilterStatusBeforePy />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryFilterStatusAfterPy />
</Tab>
</Tabs>
</Tab>
<Tab title="TypeScript">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryFilterStatusBeforeJs />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryFilterStatusAfterJs />
</Tab>
</Tabs>
</Tab>
<Tab title="Java">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryFilterStatusBeforeKt />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryFilterStatusAfterKt />
</Tab>
</Tabs>
</Tab>
<Tab title="Go">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryFilterStatusBeforeGo />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryFilterStatusAfterGo />
</Tab>
</Tabs>
</Tab>
<Tab title="cURL">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsQueryFilterStatusBeforeSh />
</Tab>
<Tab title="之后">
<SmithdbThreadsQueryFilterStatusAfterSh />
</Tab>
</Tabs>
</Tab>
</Tabs>
import SmithdbThreadsListTracesBasicBeforePy from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-before-py.mdx';
import SmithdbThreadsListTracesBasicAfterPy from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-after-py.mdx';
import SmithdbThreadsListTracesBasicBeforeJs from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-before-js.mdx';
import SmithdbThreadsListTracesBasicAfterJs from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-after-js.mdx';
import SmithdbThreadsListTracesBasicBeforeGo from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-before-go.mdx';
import SmithdbThreadsListTracesBasicAfterGo from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-after-go.mdx';
import SmithdbThreadsListTracesBasicBeforeKt from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-before-kt.mdx';
import SmithdbThreadsListTracesBasicAfterKt from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-after-kt.mdx';
import SmithdbThreadsListTracesBasicBeforeSh from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-before-sh.mdx';
import SmithdbThreadsListTracesBasicAfterSh from '/snippets/code-samples/smithdb-migration/threads-list-traces-basic-after-sh.mdx';
import SmithdbThreadsListTracesSelectingFieldsBeforePy from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-before-py.mdx';
import SmithdbThreadsListTracesSelectingFieldsAfterPy from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-after-py.mdx';
import SmithdbThreadsListTracesSelectingFieldsBeforeJs from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-before-js.mdx';
import SmithdbThreadsListTracesSelectingFieldsAfterJs from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-after-js.mdx';
import SmithdbThreadsListTracesSelectingFieldsBeforeGo from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-before-go.mdx';
import SmithdbThreadsListTracesSelectingFieldsAfterGo from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-after-go.mdx';
import SmithdbThreadsListTracesSelectingFieldsBeforeKt from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-before-kt.mdx';
import SmithdbThreadsListTracesSelectingFieldsAfterKt from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-after-kt.mdx';
import SmithdbThreadsListTracesSelectingFieldsBeforeSh from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-before-sh.mdx';
import SmithdbThreadsListTracesSelectingFieldsAfterSh from '/snippets/code-samples/smithdb-migration/threads-list-traces-selecting-fields-after-sh.mdx';
## 线程:列出追踪记录
获取特定项目中属于某个特定线程的所有追踪记录。
### 主要变更
#### 方法名称
<Tabs>
<Tab title="Python">
| 之前 | 之后 |
|--------|-------|
| `client.read_thread()` | `client.threads.list_traces()` |
<Note>
`client.threads.list_traces()` 现在是异步的。请使用 `await` 来调用它。
</Note>
完整的参数和字段列表请参阅[参考文档](https://reference.langchain.com/python/langsmith/_openapi_client/resources/threads/ThreadsResource/list_traces)。
</Tab>
<Tab title="TypeScript">
| 之前 | 之后 |
|--------|-------|
| `client.readThread()` | `client.threads.listTraces()` |
完整的参数和字段列表请参阅[参考文档](https://reference.langchain.com/javascript/langsmith/_openapi_client/Langsmith/Threads/listTraces)。
</Tab>
<Tab title="Java">
<Note>Java 从未提供过专用的按线程查询的方法。最接近的旧版等效方法是通过 `thread_id` 元数据约定进行过滤的通用运行查询。</Note>
| 之前 | 之后 |
|--------|-------|
| `client.runs().query()` (通过 `thread_id` 过滤) | `client.threads().listTraces()` |
完整的参数列表请参阅[参考文档](https://javadoc.io/doc/com.langchain.smith/langsmith-java/latest/com/langchain/smith/services/blocking/ThreadService.html)。
</Tab>
<Tab title="Go">
<Note>Go 从未提供过专用的按线程查询的方法。最接近的旧版等效方法是通过 `thread_id` 元数据约定进行过滤的通用运行查询。</Note>
| 之前 | 之后 |
|--------|-------|
| `client.Runs.Query()` (通过 `thread_id` 过滤) | `client.Threads.ListTraces()` |
完整的参数列表请参阅[参考文档](https://pkg.go.dev/github.com/langchain-ai/langsmith-go#ThreadService.ListTracesAutoPaging)。
</Tab>
<Tab title="cURL">
| 之前 | 之后 |
|--------|-------|
| `POST /api/v1/runs/query` (`filter=eq(thread_id, ...)`) | `GET /api/v2/threads/{thread_id}/traces` |
完整的参数和字段列表请参阅[API 文档](/langsmith/smith-api/threads/query-thread-traces)。
</Tab>
</Tabs>
#### 查询参数
<Tabs>
<Tab title="Python">
`read_thread` 的 `is_root` 参数没有新的对应项。`list_traces` 始终仅返回追踪记录(即根运行),这与其名称相符。`read_thread` 的 `order`(升序/降序)也没有新的对应项:结果始终按 `start_time` 升序排列,这是固定的服务器端顺序。
| 之前 (`read_thread`) | 之后 (`list_traces`) | 备注 |
|---|---|---|
| `thread_id` | `thread_id` (路径参数) | 未变更 |
| `project_id` 或 `project_name` | `project_id` | 新方法仅接受 UUID |
| `is_root` | *(不可用)* | 新方法始终仅返回追踪记录(根运行) |
| `order` | *(不可用)* | 新方法没有排序/顺序字段 |
| `filter` | `filter` | 语法相同,现在针对每个根追踪运行进行评估 |
| `select`(任意的运行字段列表) | `selects` | 新方法使用一个包含 24 个值的大写枚举 `ThreadTraceSelectField` |
| *(不可用)* | `page_size` + `cursor` | 新方法增加了游标分页 |
</Tab>
<Tab title="TypeScript">
`readThread` 的 `isRoot` 参数没有新的对应项。`listTraces` 始终仅返回追踪记录(即根运行),这与其名称相符。`readThread` 的 `order`(升序/降序)也没有新的对应项:结果始终按 `start_time` 升序排列,这是固定的服务器端顺序。
| 之前 (`readThread`) | 之后 (`listTraces`) | 备注 |
|---|---|---|
| `threadId` | `threadId` (路径参数) | 未变更 |
| `projectId` 或 `projectName` | `project_id` | 新方法仅接受 UUID |
| `isRoot` | *(不可用)* | 新方法始终仅返回追踪记录(根运行) |
| `order` | *(不可用)* | 新方法没有排序/顺序字段 |
| `filter` | `filter` | 语法相同,现在针对每个根追踪运行进行评估 |
| `select`(任意的运行字段列表) | `selects` | 新方法使用一个包含 24 个值的大写枚举 |
| *(不可用)* | `page_size` + `cursor` | 新方法增加了游标分页 |
</Tab>
<Tab title="Java">
没有需要映射的查询参数。旧版没有专用方法。`listTraces(threadId, params)` 接受 `projectId`、`filter`、`pageSize`、`cursor`、`selects`(一个包含 24 个值的枚举)。结果始终按 `startTime` 升序排列,这是固定的服务器端顺序。
</Tab>
<Tab title="Go">
没有需要映射的查询参数。旧版没有专用方法。`ListTraces(ctx, threadID, params)` 接受 `ProjectID`、`Filter`、`PageSize`、`Cursor`、`Selects`(一个包含 24 个值的枚举)。结果始终按 `StartTime` 升序排列,这是固定的服务器端顺序。
</Tab>
<Tab title="cURL">
`GET /api/v2/threads/{thread_id}/traces` 查询参数:`project_id`、`filter`、`page_size`、`cursor`、`selects`(可重复),所有字段均使用 `snake_case` 命名。结果始终按 `start_time` 升序排列,这是固定的服务器端顺序。
</Tab>
</Tabs>
#### 响应字段
<Tabs>
<Tab title="Python">
旧版的 `read_thread` 返回完整的 `Run` 对象(一个生成器)。新的 `ThreadTrace` 是轻量级的:使用预览字段(`inputs_preview`/`outputs_preview`)代替完整的 `inputs`/`outputs`,不包含嵌套的子运行。`selects` 控制填充哪些字段,这与 `traces.query` 相同。
| 之前 (旧版 `Run` 字段,通过 `read_thread`) | 之后 (新的 `ThreadTrace` 字段) | 备注 |
|---|---|---|
| `id` | *(不可用)* | 旧版根运行的 `id` 和 `trace_id` 是相同的;新 API 仅暴露 `trace_id` |
| `trace_id` | `trace_id` | 省略 `selects` 时默认返回 |
| `name` | `name` | 除非包含在 `selects` 中,否则省略 |
| `start_time` | `start_time` | 除非包含在 `selects` 中,否则省略 |
| `end_time` | `end_time` | 除非包含在 `selects` 中,否则省略 |
| `run_type` | `op` | 已重命名;编码为数字而非字符串 |
| `inputs` | `inputs_preview`,或用于未截断负载的 `inputs` | 默认为截断预览;选择 `INPUTS` 以获取完整负载 |
| `outputs` | `outputs_preview`,或用于未截断负载的 `outputs` | 默认为截断预览;选择 `OUTPUTS` 以获取完整负载 |
| `error` | `error_preview`,或用于完整消息的 `error` | 默认为截断摘要;选择 `ERROR` 以获取完整错误消息 |
| `latency` (属性) | `latency` | 原生字段,而非计算的 `timedelta` 属性 |
| `total_tokens`, `prompt_tokens`, `completion_tokens` | `total_tokens`, `prompt_tokens`, `completion_tokens` | 未变更 |
| `total_cost`, `prompt_cost`, `completion_cost` | `total_cost`, `prompt_cost`, `completion_cost` | 未变更 |
| `prompt_token_details`, `completion_token_details` | `prompt_token_details`, `completion_token_details` | 字段现在包装字典;通过 `.raw` 访问 |
| `prompt_cost_details`, `completion_cost_details` | `prompt_cost_details`, `completion_cost_details` | 字段现在包装字典;通过 `.raw` 访问 |
| `first_token_time` | `first_token_time` | 除非包含在 `selects` 中,否则省略 |
| *(不可用)* | `thread_id` | 新增:此追踪记录所属的线程 UUID |
| `child_runs`, `child_run_ids` | *(不可用)* | 不包含嵌套的子运行;使用 `traces.list_runs` 获取后代运行 |
</Tab>
<Tab title="TypeScript">
旧版的 `readThread` 返回完整的 `Run` 对象(一个异步生成器)。新的 `ThreadTrace` 是轻量级的:使用预览字段(`inputs_preview`/`outputs_preview`)代替完整的 `inputs`/`outputs`,不包含嵌套的子运行。`selects` 控制填充哪些字段,这与 `traces.query` 相同。
| 之前 (旧版 `Run` 字段,通过 `readThread`) | 之后 (新的 `ThreadTrace` 字段) | 备注 |
|---|---|---|
| `id` | *(不可用)* | 旧版根运行的 `id` 和 `trace_id` 是相同的;新 API 仅暴露 `trace_id` |
| `trace_id` | `trace_id` | 省略 `selects` 时默认返回 |
| `name` | `name` | 除非包含在 `selects` 中,否则省略 |
| `start_time` | `start_time` | 除非包含在 `selects` 中,否则省略 |
| `end_time` | `end_time` | 除非包含在 `selects` 中,否则省略 |
| `run_type` | `op` | 已重命名;编码为数字而非字符串 |
| `inputs` | `inputs_preview`,或用于未截断负载的 `inputs` | 默认为截断预览;选择 `INPUTS` 以获取完整负载 |
| `outputs` | `outputs_preview`,或用于未截断负载的 `outputs` | 默认为截断预览;选择 `OUTPUTS` 以获取完整负载 |
| `error` | `error_preview`,或用于完整消息的 `error` | 默认为截断摘要;选择 `ERROR` 以获取完整错误消息 |
| `latency` | `latency` | 新类型上的原生字段 |
| `total_tokens`, `prompt_tokens`, `completion_tokens` | `total_tokens`, `prompt_tokens`, `completion_tokens` | 未变更 |
| `total_cost`, `prompt_cost`, `completion_cost` | `total_cost`, `prompt_cost`, `completion_cost` | 未变更 |
| `prompt_token_details`, `completion_token_details` | `prompt_token_details`, `completion_token_details` | 未变更 |
| `prompt_cost_details`, `completion_cost_details` | `prompt_cost_details`, `completion_cost_details` | 未变更 |
| `first_token_time` | `first_token_time` | 除非包含在 `selects` 中,否则省略 |
| *(不可用)* | `thread_id` | 新增:此追踪记录所属的线程 UUID |
| `child_runs`, `child_run_ids` | *(不可用)* | 不包含嵌套的子运行;使用 `traces.listRuns` 获取后代运行 |
</Tab>
<Tab title="Java">
`ThreadTrace` 有 24 个 `Optional` 字段:`traceId`、`threadId`、`name`、`startTime`、`endTime`、`latency`、`op`、带有每类 `_details` 的 token/cost 字段、`inputsPreview`/`outputsPreview`/`inputs`/`outputs`、`errorPreview`/`error`、`firstTokenTime`。
| 之前 (旧版 `RunSchema` 方法) | 之后 (新的 `ThreadTrace` 方法) | 备注 |
|---|---|---|
| `id()` | *(不可用)* | 旧版根运行的 `id()` 和 `traceId()` 是相同的;新 API 仅暴露 `traceId()` |
| `traceId()` | `traceId()` | 省略 `selects` 时默认返回 |
| `name()` | `name()` | 除非包含在 `selects` 中,否则省略 |
| `startTime()` | `startTime()` | 除非包含在 `selects` 中,否则省略 |
| `endTime()` | `endTime()` | 除非包含在 `selects` 中,否则省略 |
| `runType()` | `op()` | 已重命名;编码为数字而非字符串 |
| `inputs()` | `inputsPreview()`,或用于未截断负载的 `inputs()` | 默认为截断预览;选择 `INPUTS` 以获取完整负载 |
| `outputs()` | `outputsPreview()`,或用于未截断负载的 `outputs()` | 默认为截断预览;选择 `OUTPUTS` 以获取完整负载 |
| `error()` | `errorPreview()`,或用于完整消息的 `error()` | 默认为截断摘要;选择 `ERROR` 以获取完整错误消息 |
| `latency()` | `latency()` | 未变更 |
| `totalTokens()`, `promptTokens()`, `completionTokens()` | `totalTokens()`, `promptTokens()`, `completionTokens()` | 未变更 |
| `totalCost()`, `promptCost()`, `completionCost()` | `totalCost()`, `promptCost()`, `completionCost()` | 未变更 |
| `promptTokenDetails()`, `completionTokenDetails()` | `promptTokenDetails()`, `completionTokenDetails()` | 未变更 |
| `promptCostDetails()`, `completionCostDetails()` | `promptCostDetails()`, `completionCostDetails()` | 未变更 |
| `firstTokenTime()` | `firstTokenTime()` | 除非包含在 `selects` 中,否则省略 |
| *(不可用)* | `threadId()` | 新增:此追踪记录所属的线程 UUID |
| `childRuns()`, `childRunIds()` | *(不可用)* | 不包含嵌套的子运行;使用 `traces().listRuns()` 获取后代运行 |
</Tab>
<Tab title="Go">
`ThreadTrace` 有 24 个字段,使用 Go 结构体的 `PascalCase` 形式。
| 之前 (旧版根 `Run` 字段) | 之后 (新的 `ThreadTrace` 字段) | 备注 |
|---|---|---|
| `ID` | *(不可用)* | 旧版根运行的 `ID` 和 `TraceID` 是相同的;新 API 仅暴露 `TraceID` |
| `TraceID` | `TraceID` | 省略 `Selects` 时默认返回 |
| `Name` | `Name` | 除非包含在 `Selects` 中,否则省略 |
| `StartTime` | `StartTime` | 除非包含在 `Selects` 中,否则省略 |
| `EndTime` | `EndTime` | 除非包含在 `Selects` 中,否则省略 |
| `RunType` | `Op` | 已重命名;编码为数字而非字符串 |
| `Inputs` | `InputsPreview`,或用于未截断负载的 `Inputs` | 默认为截断预览;选择 `INPUTS` 以获取完整负载 |
| `Outputs` | `OutputsPreview`,或用于未截断负载的 `Outputs` | 默认为截断预览;选择 `OUTPUTS` 以获取完整负载 |
| `Error` | `ErrorPreview`,或用于完整消息的 `Error` | 默认为截断摘要;选择 `ERROR` 以获取完整错误消息 |
| `Latency` | `Latency` | 未变更 |
| `TotalTokens`, `PromptTokens`, `CompletionTokens` | `TotalTokens`, `PromptTokens`, `CompletionTokens` | 未变更 |
| `TotalCost`, `PromptCost`, `CompletionCost` | `TotalCost`, `PromptCost`, `CompletionCost` | 未变更 |
| `PromptTokenDetails`, `CompletionTokenDetails` | `PromptTokenDetails`, `CompletionTokenDetails` | 未变更 |
| `PromptCostDetails`, `CompletionCostDetails` | `PromptCostDetails`, `CompletionCostDetails` | 未变更 |
| `FirstTokenTime` | `FirstTokenTime` | 除非包含在 `Selects` 中,否则省略 |
| *(不可用)* | `ThreadID` | 新增:此追踪记录所属的线程 UUID |
| `ChildRuns`, `ChildRunIDs` | *(不可用)* | 不包含嵌套的子运行;使用 `Traces.ListRuns` 获取后代运行 |
</Tab>
<Tab title="cURL">
JSON 响应字段使用 `snake_case`,与下表匹配。
| 之前 (旧版根运行字段) | 之后 (新的 `ThreadTrace` 字段) | 备注 |
|---|---|---|
| `id` | *(不可用)* | 旧版根运行的 `id` 和 `trace_id` 是相同的;新 API 仅暴露 `trace_id` |
| `trace_id` | `trace_id` | 省略 `selects` 时默认返回 |
| `name` | `name` | 除非包含在 `selects` 中,否则省略 |
| `start_time` | `start_time` | 除非包含在 `selects` 中,否则省略 |
| `end_time` | `end_time` | 除非包含在 `selects` 中,否则省略 |
| `run_type` | `op` | 已重命名;编码为数字而非字符串 |
| `inputs` | `inputs_preview`,或用于未截断负载的 `inputs` | 默认为截断预览;选择 `INPUTS` 以获取完整负载 |
| `outputs` | `outputs_preview`,或用于未截断负载的 `outputs` | 默认为截断预览;选择 `OUTPUTS` 以获取完整负载 |
| `error` | `error_preview`,或用于完整消息的 `error` | 默认为截断摘要;选择 `ERROR` 以获取完整错误消息 |
| `latency` | `latency` | 未变更 |
| `total_tokens`, `prompt_tokens`, `completion_tokens` | `total_tokens`, `prompt_tokens`, `completion_tokens` | 未变更 |
| `total_cost`, `prompt_cost`, `completion_cost` | `total_cost`, `prompt_cost`, `completion_cost` | 未变更 |
| `prompt_token_details`, `completion_token_details` | `prompt_token_details`, `completion_token_details` | 未变更 |
| `prompt_cost_details`, `completion_cost_details` | `prompt_cost_details`, `completion_cost_details` | 未变更 |
| `first_token_time` | `first_token_time` | 除非包含在 `selects` 中,否则省略 |
| *(不可用)* | `thread_id` | 新增:此追踪记录所属的线程 UUID |
| `child_runs`, `child_run_ids` | *(不可用)* | 不包含嵌套的子运行;使用 `traces.list_runs` 获取后代运行 |
</Tab>
</Tabs>
### 示例
#### 列出线程中的每条追踪记录(对话轮次)
获取属于一个线程的所有追踪记录(对话轮次)。
<Tabs>
<Tab title="Python">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesBasicBeforePy />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesBasicAfterPy />
</Tab>
</Tabs>
</Tab>
<Tab title="TypeScript">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesBasicBeforeJs />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesBasicAfterJs />
</Tab>
</Tabs>
</Tab>
<Tab title="Java">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesBasicBeforeKt />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesBasicAfterKt />
</Tab>
</Tabs>
</Tab>
<Tab title="Go">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesBasicBeforeGo />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesBasicAfterGo />
</Tab>
</Tabs>
</Tab>
<Tab title="cURL">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesBasicBeforeSh />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesBasicAfterSh />
</Tab>
</Tabs>
</Tab>
</Tabs>
#### 选择追踪记录的特定字段
只请求你需要的字段,而不是所有字段,以减少响应大小。
<Tabs>
<Tab title="Python">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesSelectingFieldsBeforePy />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesSelectingFieldsAfterPy />
</Tab>
</Tabs>
</Tab>
<Tab title="TypeScript">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesSelectingFieldsBeforeJs />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesSelectingFieldsAfterJs />
</Tab>
</Tabs>
</Tab>
<Tab title="Java">
<Note>之前的示例在此处省略了 `total_cost`。在旧版 `RunSchema` 类型上选择该字段会触发当前 Java 绑定中的一个已知反序列化错误(它期望一个字符串,但 API 返回的是一个数字)。</Note>
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesSelectingFieldsBeforeKt />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesSelectingFieldsAfterKt />
</Tab>
</Tabs>
</Tab>
<Tab title="Go">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesSelectingFieldsBeforeGo />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesSelectingFieldsAfterGo />
</Tab>
</Tabs>
</Tab>
<Tab title="cURL">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbThreadsListTracesSelectingFieldsBeforeSh />
</Tab>
<Tab title="之后">
<SmithdbThreadsListTracesSelectingFieldsAfterSh />
</Tab>
</Tabs>
</Tab>
</Tabs>
数据集实验运行:查询
查询数据集示例以及针对每个示例记录的实验运行。接受一个或多个experiment_ids,以便您可以并排查看来自多个实验的运行;结果以基于游标的分页页面形式返回。
主要变更
方法名称
- Python
- TypeScript
- Java
- Go
- cURL
| 之前 | 之后 |
|---|---|
client.get_experiment_results() | client.datasets.experiment_runs.query() |
client.datasets.experiment_runs.query() 现在是异步的。请使用 await 调用它。| 之前 | 之后 |
|---|---|
(没有旧的公共 Client 方法) | client.datasets.experimentRuns.query() |
| 之前 | 之后 |
|---|---|
client.datasets().runs().query() | client.datasets().experimentRuns().query() |
| 之前 | 之后 |
|---|---|
client.Datasets.Runs.Query() | client.Datasets.ExperimentRuns.Query() |
| 之前 | 之后 |
|---|---|
POST /api/v1/datasets/{dataset_id}/runs | POST /api/v2/datasets/{dataset_id}/experiment-runs |
查询参数
- Python
- TypeScript
- Java
- Go
- cURL
experiment_ids 是必需的,并替代了 session_ids。其值仍然是实验追踪项目的 UUID——如果你只知道实验名称,请先解析它:client.read_project(project_name="my-experiment").id,或在异步代码中使用 await client.aread_project(project_name="my-experiment")。之前 (get_experiment_results) | 之后 (datasets.experiment_runs.query) | 备注 |
|---|---|---|
project_id | experiment_ids | get_experiment_results 接受一个项目/实验;新方法接受一个必需的非空列表 |
limit | (已移除) | 使用 page_size 设置每批次请求数量 |
| (不可用) | page_size | 每次请求的结果数量(默认 20,最大 100) |
| (内部处理) | cursor | 传递上一页的 next_cursor 以获取下一页 |
preview | selects | 省略 selects 则仅返回运行 ID;使用 INPUTS_PREVIEW 和 OUTPUTS_PREVIEW 获取预览,或使用 INPUTS 和 OUTPUTS 获取完整内容 |
| (未公开) | sort | 使用 {by, order} 进行反馈分数排序 |
filters | filters | 未变;将实验 UUID 字符串映射到筛选表达式 |
comparative_experiment_id | comparative_experiment_id | 未变 |
| (未公开) | example_ids | 可选的示例 UUID 筛选条件,最多 1000 个 |
experiment_ids 是必需的,并替代了 session_ids。其值仍然是实验追踪项目的 UUID——如果你只知道实验名称,请先解析它:(await client.readProject({ projectName: "my-experiment" })).id。| 之前 | 之后 (datasets.experimentRuns.query) | 备注 |
|---|---|---|
(没有旧的公共 Client 方法) | experiment_ids | 必需且非空 |
(没有旧的公共 Client 方法) | page_size | 默认 20,最大 100 |
(没有旧的公共 Client 方法) | cursor | 传递上一页的 next_cursor 而不是数字偏移量 |
(没有旧的公共 Client 方法) | selects | 省略 selects 则仅返回运行 ID;使用 INPUTS_PREVIEW 和 OUTPUTS_PREVIEW 获取预览,或使用 INPUTS 和 OUTPUTS 获取完整内容 |
(没有旧的公共 Client 方法) | sort | 使用 { by, order } 进行反馈分数排序 |
(没有旧的公共 Client 方法) | filters | 将实验 UUID 字符串映射到筛选表达式 |
(没有旧的公共 Client 方法) | comparative_experiment_id | 限定成对标注的反馈范围 |
(没有旧的公共 Client 方法) | example_ids | 可选的示例 UUID 筛选条件,最多 1000 个 |
experimentIds() 是必需的,并替代了 sessionIds()。其值仍然是实验追踪项目的 UUID——如果你只知道实验名称,请先解析它:client.sessions().list(SessionListParams.builder().name("my-experiment").build()).items().first().id()。之前 (RunQueryParams) | 之后 (ExperimentRunQueryParams) | 备注 |
|---|---|---|
sessionIds() | experimentIds() | 已重命名;必需且非空 |
limit() | (已移除) | 使用 pageSize() 设置每批次请求数量 |
| (不可用) | pageSize() | 每次请求的结果数量(默认 20,最大 100) |
offset() | cursor() | 传递上一页的 nextCursor() 而不是数字偏移量 |
preview() | selects() | 省略 selects 则仅返回运行 ID;添加 Select.INPUTS_PREVIEW 和 Select.OUTPUTS_PREVIEW 以获取预览 |
sortParams() | sort() | 形式从 sortBy() / sortOrder() 变为 by() / order() |
filters() | filters() | 未变 |
comparativeExperimentId() | comparativeExperimentId() | 未变 |
exampleIds() | exampleIds() | 未变,最多 1000 个 |
format() | (已移除) | 新端点仅返回 JSON |
includeAnnotatorDetail() | (已移除) | 没有新的 JSON 等效项 |
ExperimentIDs 是必需的,并替代了 SessionIDs。其值仍然是实验追踪项目的 UUID——如果你只知道实验名称,请先解析它:按 Name 筛选列出会话,然后取第一个结果的 ID。之前 (DatasetRunQueryParams) | 之后 (DatasetExperimentRunQueryParams) | 备注 |
|---|---|---|
SessionIDs | ExperimentIDs | 已重命名;必需且非空 |
Limit | (已移除) | 使用 PageSize 设置每批次请求数量 |
| (不可用) | PageSize | 每次请求的结果数量(默认 20,最大 100) |
Offset | Cursor | 传递上一页的 NextCursor 而不是数字偏移量 |
Preview | Selects | 省略 selects 则仅返回运行 ID;使用 InputsPreview 和 OutputsPreview 选择常量获取预览 |
SortParams | Sort | 形式从 SortBy / SortOrder 变为 By / Order |
Filters | Filters | 未变 |
ComparativeExperimentID | ComparativeExperimentID | 未变 |
ExampleIDs | ExampleIDs | 未变,最多 1000 个 |
Format | (已移除) | 新端点仅返回 JSON |
IncludeAnnotatorDetail | (已移除) | 没有新的 JSON 等效项 |
experiment_ids 是必需的,并替代了 session_ids。其值仍然是实验追踪项目的 UUID——如果你只知道实验名称,请先解析它:GET /api/v1/sessions?name=my-experiment 并取 .[0].id。之前 (POST /api/v1/datasets/{dataset_id}/runs 请求体) | 之后 (POST /api/v2/datasets/{dataset_id}/experiment-runs 请求体) | 备注 |
|---|---|---|
session_ids | experiment_ids | 已重命名;必需且非空 |
limit | (已移除) | 使用 page_size 设置每批次请求数量 |
| (不可用) | page_size | 每次请求的结果数量(默认 20,最大 100) |
offset | cursor | 传递上一页的 next_cursor 而不是数字偏移量 |
preview | selects | 省略 selects 则仅返回运行 ID;使用 INPUTS_PREVIEW 和 OUTPUTS_PREVIEW 获取预览,或使用 INPUTS 和 OUTPUTS 获取完整内容 |
sort_params | sort | 形式从 {sort_by, sort_order} 变为 {by, order} |
filters | filters | 未变;将实验 UUID 字符串映射到筛选表达式 |
comparative_experiment_id | comparative_experiment_id | 未变 |
example_ids | example_ids | 未变,最多 1000 个 |
format=csv | (已移除) | 新端点仅返回 JSON |
include_annotator_detail | (已移除) | 没有新的 JSON 等效项 |
响应字段
每个页面项是一个数据集示例及其产生的运行——不是裸露的Run。其 runs 字段包含与查询运行相同的 Run 对象;有关每个运行的字段,请参阅该部分。下面的表格描述了该项的其余部分:示例字段以及 runs。
- Python
- TypeScript
- Java
- Go
- cURL
get_experiment_results 返回带有 examples_with_runs 迭代器的实验结果。datasets.experiment_runs.query 返回一个分页页面对象(page.items, page.next_cursor);每个项包含:| 字段 | 备注 |
|---|---|
id | 数据集示例 UUID |
dataset_id | 父数据集 UUID |
name | 示例名称(如果已设置) |
created_at / modified_at | 示例时间戳 |
inputs / outputs | 示例输入和参考输出内容 |
metadata | 示例元数据 |
source_run_id | 创建该示例的运行 UUID(如果有的话) |
attachment_urls | 每个附件名称对应的预签名下载 URL |
runs | 此示例的运行——参见查询运行 |
旧版数据集运行端点未在公共 TypeScript
Client 上公开。datasets.experimentRuns.query 返回一个分页页面(page.getPaginatedItems(), page.next_cursor);每个项包含:| 字段 | 备注 |
|---|---|
id | 数据集示例 UUID |
dataset_id | 父数据集 UUID |
name | 示例名称(如果已设置) |
created_at / modified_at | 示例时间戳 |
inputs / outputs | 示例输入和参考输出内容 |
metadata | 示例元数据 |
source_run_id | 创建该示例的运行 UUID(如果有的话) |
attachment_urls | 每个附件名称对应的预签名下载 URL |
runs | 此示例的运行——参见查询运行 |
runs().query 返回一个可选列表。experimentRuns().query 返回一个页面对象(items(), nextCursor());每个项包含:| 字段 | 备注 |
|---|---|
id() | 数据集示例 UUID |
datasetId() | 父数据集 UUID |
name() | 示例名称(如果已设置) |
createdAt() / modifiedAt() | 示例时间戳 |
inputs() / outputs() | 示例输入和参考输出内容 |
metadata() | 示例元数据 |
sourceRunId() | 创建该示例的运行 UUID(如果有的话) |
attachmentUrls() | 每个附件名称对应的预签名下载 URL |
runs() | 此示例的运行——参见查询运行 |
Datasets.Runs.Query 返回一个切片指针。Datasets.ExperimentRuns.Query 返回一个 ItemsCursorPostPagination(Items, NextCursor);每个项包含:| 字段 | 备注 |
|---|---|
ID | 数据集示例 UUID |
DatasetID | 父数据集 UUID |
Name | 示例名称(如果已设置) |
CreatedAt / ModifiedAt | 示例时间戳 |
Inputs / Outputs | 示例输入和参考输出内容 |
Metadata | 示例元数据 |
SourceRunID | 创建该示例的运行 UUID(如果有的话) |
AttachmentURLs | 每个附件名称对应的预签名下载 URL |
Runs | 此示例的运行——参见查询运行 |
POST /api/v1/datasets/{dataset_id}/runs 返回一个 JSON 数组。POST /api/v2/datasets/{dataset_id}/experiment-runs 返回 { "items": [...], "next_cursor": "..." };每个项包含:| 字段 | 备注 |
|---|---|
id | 数据集示例 UUID |
dataset_id | 父数据集 UUID |
name | 示例名称(如果已设置) |
created_at / modified_at | 示例时间戳 |
inputs / outputs | 示例输入和参考输出内容 |
metadata | 示例元数据 |
source_run_id | 创建该示例的运行 UUID(如果有的话) |
attachment_urls | 每个附件名称对应的预签名下载 URL |
runs | 此示例的运行——参见查询运行 |
示例
查询实验运行并请求预览字段
- Python
- TypeScript
- Java
- Go
- cURL
旧版中
preview=True 会自动返回截断的输入/输出。在新 API 中,需要明确请求:在 selects 中传递 INPUTS_PREVIEW 和 OUTPUTS_PREVIEW 以获取相同的截断形式,或传递 INPUTS/OUTPUTS 以获取未截断的值。省略 selects 则仅返回 id。- 之前
- 之后
Before
from langsmith import Client
client = Client()
experiment_id = client.read_project(project_name=experiment_name).id
results = client.get_experiment_results(
project_id=experiment_id,
limit=20,
preview=True,
)
examples_with_runs = list(results["examples_with_runs"])
After
from langsmith import Client
import asyncio
async def main():
client = Client()
experiment_id = client.read_project(project_name=experiment_name).id
page = await client.datasets.experiment_runs.query(
str(dataset_id),
experiment_ids=[str(experiment_id)],
page_size=20,
selects=["ID", "NAME", "STATUS", "INPUTS_PREVIEW", "OUTPUTS_PREVIEW"],
)
return page.items
examples_with_runs = asyncio.run(main())
新版 TypeScript SDK 方法公开了实验运行查询端点。旧版直接端点请求形式显示在 cURL 选项卡中。在
selects 中传递 INPUTS_PREVIEW 和 OUTPUTS_PREVIEW 以获取截断的输入/输出,或传递 INPUTS/OUTPUTS 以获取未截断的值。省略 selects 则仅返回 id。- 之前
- 之后
Before
// 旧版数据集运行端点未在公共TypeScript客户端上暴露。
// 请使用 cURL 示例获取旧的请求体格式。
After
import { Client } from "langsmith";
const client = new Client();
const experimentId = (await client.readProject({ projectName: experimentName })).id;
const page = await client.datasets.experimentRuns.query(datasetId, {
experiment_ids: [experimentId],
page_size: 20,
selects: ["ID", "NAME", "STATUS", "INPUTS_PREVIEW", "OUTPUTS_PREVIEW"],
});
const examplesWithRuns = page.getPaginatedItems();
旧版中
preview(true) 会自动返回截断的输入/输出。在新 API 中,需要明确请求:添加 Select.INPUTS_PREVIEW 和 Select.OUTPUTS_PREVIEW 以获取相同的截断形式,或添加 Select.INPUTS/Select.OUTPUTS 以获取未截断的值。省略 selects 则仅返回 id。- 之前
- 之后
Before
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.datasets.runs.RunQueryParams
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val examplesWithRuns = client.datasets().runs().query(
datasetId,
RunQueryParams.builder()
.addSessionId(experimentId)
.limit(20L)
.preview(true)
.build()
)
After
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.datasets.experimentruns.ExperimentRunQueryParams
import com.langchain.smith.models.runs.RunSelectField
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val page = client.datasets().experimentRuns().query(
datasetId,
ExperimentRunQueryParams.builder()
.addExperimentId(experimentId)
.pageSize(20L)
.addSelect(RunSelectField.ID)
.addSelect(RunSelectField.NAME)
.addSelect(RunSelectField.STATUS)
.addSelect(RunSelectField.INPUTS_PREVIEW)
.addSelect(RunSelectField.OUTPUTS_PREVIEW)
.build()
)
val examplesWithRuns = page.items()
旧版中
Preview: true 会自动返回截断的输入/输出。在新 API 中,需要明确请求:添加 InputsPreview 和 OutputsPreview 选择常量以获取相同的截断形式,或添加 Inputs/Outputs 以获取未截断的值。省略 selects 则仅返回 ID。- 之前
- 之后
Before
package main
import (
"context"
"github.com/langchain-ai/langsmith-go"
)
ctx := context.Background()
client := langsmith.NewClient()
examplesWithRuns, err := client.Datasets.Runs.Query(ctx, datasetID, langsmith.DatasetRunQueryParams{
SessionIDs: langsmith.F([]string{experimentID}),
Limit: langsmith.F(int64(20)),
Preview: langsmith.F(true),
})
After
package main
import (
"context"
"github.com/langchain-ai/langsmith-go"
)
ctx := context.Background()
client := langsmith.NewClient()
page, err := client.Datasets.ExperimentRuns.Query(ctx, datasetID, langsmith.DatasetExperimentRunQueryParams{
ExperimentIDs: langsmith.F([]string{experimentID}),
PageSize: langsmith.F(int64(20)),
Selects: langsmith.F([]langsmith.RunSelectField{
langsmith.RunSelectFieldID,
langsmith.RunSelectFieldName,
langsmith.RunSelectFieldStatus,
langsmith.RunSelectFieldInputsPreview,
langsmith.RunSelectFieldOutputsPreview,
}),
})
旧版中
preview: true 会自动返回截断的输入/输出。在新 API 中,需要明确请求:在 selects 中传递 INPUTS_PREVIEW 和 OUTPUTS_PREVIEW 以获取相同的截断形式,或传递 INPUTS/OUTPUTS 以获取未截断的值。省略 selects 则仅返回 id。- 之前
- 之后
Before
curl -X POST "https://api.smith.langchain.com/api/v1/datasets/$DATASET_ID/runs" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg eid "$EXPERIMENT_ID" '{
"session_ids": [$eid],
"limit": 20,
"preview": true
}')"
After
curl -X POST "https://api.smith.langchain.com/api/v2/datasets/$DATASET_ID/experiment-runs" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg eid "$EXPERIMENT_ID" '{
"experiment_ids": [$eid],
"page_size": 20,
"selects": ["ID", "NAME", "STATUS", "INPUTS_PREVIEW", "OUTPUTS_PREVIEW"]
}')"
分页获取结果
以下两个示例都会获取最多 100 条结果,跨尽可能多的页,然后停止——因此这是两个可比的操作,而不是“一页”与“全部”。根据你自己的用例调整100/page_size 的值。
- Python
- TypeScript
- Java
- Go
- cURL
get_experiment_results 内部进行分页,并在返回 limit 个总结果后停止。datasets.experiment_runs.query 没有总数 limit;使用 async for 迭代返回的页面,并在获取足够数量后使用 break 停止。- 之前
- 之后
Before
from langsmith import Client
client = Client()
experiment_id = client.read_project(project_name=experiment_name).id
# get_experiment_results 内部已进行分页处理;增加 `limit` 参数可以在单次调用中获取更多结果。无需手动传递游标。
results = client.get_experiment_results(
project_id=experiment_id,
limit=100,
)
examples_with_runs = list(results["examples_with_runs"])
After
from langsmith import Client
import asyncio
async def main():
client = Client()
experiment_id = client.read_project(project_name=experiment_name).id
page = await client.datasets.experiment_runs.query(
str(dataset_id),
experiment_ids=[str(experiment_id)],
page_size=1,
)
runs = []
async for run in page:
runs.append(run)
if len(runs) >= 100:
break
return runs
examples_with_runs = asyncio.run(main())
旧版数据集运行端点未在公共 TypeScript
Client 上公开。client.datasets.experimentRuns.query(...) 返回一个异步可迭代对象——使用 for await...of(无需额外的 await)并在获取足够数量后使用 break 停止。- 之前
- 之后
Before
// 遗留数据集运行端点未在公共 TypeScript 客户端中公开。
// 请使用 cURL 示例作为旧请求体结构。
After
import { Client } from "langsmith";
const client = new Client();
const experimentId = (await client.readProject({ projectName: experimentName })).id;
const runs: unknown[] = [];
for await (const run of client.datasets.experimentRuns.query(datasetId, {
experiment_ids: [experimentId],
page_size: 1,
})) {
runs.push(run);
if (runs.length >= 100) break;
}
旧版端点每次调用返回一页,没有自动分页——手动循环,递增
offset,并在获取足够数量后停止。.experimentRuns().query(...).autoPager() 会为你遍历页面——一旦有足够的运行就跳出循环。- 之前
- 之后
代码示例
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.datasets.runs.RunQueryParams
import com.langchain.smith.models.datasets.runs.ExampleWithRunsCh
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val examplesWithRuns = mutableListOf<ExampleWithRunsCh>()
var offset = 0L
val limit = 20L
while (true) {
val page = client.datasets().runs().query(
datasetId,
RunQueryParams.builder()
.addSessionId(experimentId)
.limit(limit)
.offset(offset)
.build()
).orElse(emptyList())
examplesWithRuns.addAll(page)
if (examplesWithRuns.size >= 100 || page.size.toLong() < limit) break
offset += limit
}
After
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.datasets.experimentruns.ExperimentRunQueryParams
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val page = client.datasets().experimentRuns().query(
datasetId,
ExperimentRunQueryParams.builder()
.addExperimentId(experimentId)
.pageSize(1L)
.build()
)
var count = 0
for (run in page.autoPager()) {
count++
if (count >= 100) break
}
旧版端点每次调用返回一页,没有自动分页——手动循环,递增
Offset,并在获取足够数量后停止。在新端点上,通过在请求中设置上一个响应 NextCursor 的 Cursor 来手动分页,并在获取足够数量后停止;避免在此处使用 QueryAutoPaging——它将游标作为查询参数发送,而此 POST 端点不读取该参数,因此它会静默地永远重新获取第一页。- 之前
- 之后
Before
package main
import (
"context"
"github.com/langchain-ai/langsmith-go"
)
ctx := context.Background()
client := langsmith.NewClient()
var examplesWithRuns []langsmith.ExampleWithRunsCh
offset := int64(0)
limit := int64(20)
for {
page, err := client.Datasets.Runs.Query(ctx, datasetID, langsmith.DatasetRunQueryParams{
SessionIDs: langsmith.F([]string{experimentID}),
Limit: langsmith.F(limit),
Offset: langsmith.F(offset),
})
examplesWithRuns = append(examplesWithRuns, *page...)
if len(examplesWithRuns) >= 100 || int64(len(*page)) < limit {
break
}
offset += limit
}
After
package main
import (
"context"
"github.com/langchain-ai/langsmith-go"
)
ctx := context.Background()
client := langsmith.NewClient()
params := langsmith.DatasetExperimentRunQueryParams{
ExperimentIDs: langsmith.F([]string{experimentID}),
PageSize: langsmith.F(int64(1)),
}
var examplesWithRuns []langsmith.DatasetExperimentRunQueryResponse
for {
page, err := client.Datasets.ExperimentRuns.Query(ctx, datasetID, params)
examplesWithRuns = append(examplesWithRuns, page.Items...)
if page.NextCursor == "" || len(examplesWithRuns) >= 100 {
break
}
params.Cursor = langsmith.F(page.NextCursor)
}
原始 HTTP 没有自动分页助手:将上一个响应的
next_cursor 作为 cursor 传回以获取下一页。- 之前
- 之后
Before
curl -X POST "https://api.smith.langchain.com/api/v1/datasets/$DATASET_ID/runs" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg eid "$EXPERIMENT_ID" '{
"session_ids": [$eid],
"limit": 20,
"offset": 20
}')"
After
curl -X POST "https://api.smith.langchain.com/api/v2/datasets/$DATASET_ID/experiment-runs" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg eid "$EXPERIMENT_ID" --arg cursor "$NEXT_CURSOR" '{
"experiment_ids": [$eid],
"page_size": 20,
"cursor": $cursor
}')"
按反馈分数排序
按反馈分数对数据集示例排序,仅在查询单个实验时支持。在 Go 和 Java 中,这替代了旧版的sort_params.sort_by/sort_params.sort_order(现在是 sort.by/sort.order);Python 和 TypeScript 在新 API 中首次获得排序功能。
- Python
- TypeScript
- Java
- Go
- cURL
get_experiment_results 不支持按反馈分数排序。- 之前
- 之后
# get_experiment_results 不支持按反馈分数对结果进行排序。
After
from langsmith import Client
import asyncio
async def main():
client = Client()
experiment_id = client.read_project(project_name=experiment_name).id
page = await client.datasets.experiment_runs.query(
str(dataset_id),
experiment_ids=[str(experiment_id)],
sort={"by": "feedback.correctness", "order": "ASC"},
)
return page.items
examples_with_runs = asyncio.run(main())
旧版数据集运行端点未在公共 TypeScript
Client 上公开,因此在新 API 之前无法按反馈分数排序。- 之前
- 之后
Before
// 旧版数据集运行端点未在公共TypeScript客户端上暴露。
// 对于旧的请求体格式,请使用cURL示例。
之后
import { Client } from "langsmith";
const client = new Client();
const experimentId = (await client.readProject({ projectName: experimentName })).id;
const page = await client.datasets.experimentRuns.query(datasetId, {
experiment_ids: [experimentId],
sort: { by: "feedback.correctness", order: "ASC" },
});
sortParams() 被 sort() 替代,其中 sortBy()/sortOrder() 重命名为 by()/order()。- 之前
- 之后
Before
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.datasets.runs.RunQueryParams
import com.langchain.smith.models.datasets.runs.SortParamsForRunsComparisonView
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val examplesWithRuns = client.datasets().runs().query(
datasetId,
RunQueryParams.builder()
.addSessionId(experimentId)
.sortParams(
SortParamsForRunsComparisonView.builder()
.sortBy("正确性")
.sortOrder(SortParamsForRunsComparisonView.SortOrder.ASC)
.build()
)
.build()
)
After
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.datasets.experimentruns.ExperimentRunQueryParams
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
val page = client.datasets().experimentRuns().query(
datasetId,
ExperimentRunQueryParams.builder()
.addExperimentId(experimentId)
.sort(
ExperimentRunQueryParams.Sort.builder()
.by("feedback.correctness")
.order("ASC")
.build()
)
.build()
)
SortParams 被 Sort 替代,其中 SortBy/SortOrder 重命名为 By/Order。- 之前
- 之后
Before
package main
import (
"context"
"github.com/langchain-ai/langsmith-go"
)
ctx := context.Background()
client := langsmith.NewClient()
examplesWithRuns, err := client.Datasets.Runs.Query(ctx, datasetID, langsmith.DatasetRunQueryParams{
SessionIDs: langsmith.F([]string{experimentID}),
SortParams: langsmith.F(langsmith.SortParamsForRunsComparisonView{
SortBy: langsmith.F("正确性"),
SortOrder: langsmith.F(langsmith.SortParamsForRunsComparisonViewSortOrderAsc),
}),
})
After
package main
import (
"context"
"github.com/langchain-ai/langsmith-go"
)
ctx := context.Background()
client := langsmith.NewClient()
page, err := client.Datasets.ExperimentRuns.Query(ctx, datasetID, langsmith.DatasetExperimentRunQueryParams{
ExperimentIDs: langsmith.F([]string{experimentID}),
Sort: langsmith.F(langsmith.DatasetExperimentRunQueryParamsSort{
By: langsmith.F("feedback.correctness"),
Order: langsmith.F("ASC"),
}),
})
- 之前
- 之后
已收到您的 MDX 文档翻译指令。我已详细阅读并理解所有规则:
- 格式与结构:将严格保留所有 Markdown 格式(标题、列表、链接、表格等)及 JSX 组件的完整结构与语法。
- 代码块处理:仅翻译代码块内的自然语言注释和面向读者的字符串说明,绝不会修改代码语法、变量名、函数名、类名、导入路径或命令。
- 代码块标记:绝不会翻译代码块标记本身(例如 ```shell title=“Output”)。
- JSX/HTML 标签:绝不会翻译 JSX 组件标签、HTML 标签及其任何属性。
- Frontmatter:不会翻译以
---包围的配置项中的键名,仅翻译其对应的值。 - 语言风格:确保译文通俗易懂,符合中文阅读习惯和专业语境。
- 日志字段:仅翻译日志字段名(如
Status)之后的自然语言内容,字段名本身不翻译。 - 保护占位符:将逐字保留文档中所有形如
@@MDX_PRESERVE_...@@的占位符,不做任何翻译、改写或处理。
Before
curl -X POST "https://api.smith.langchain.com/api/v1/datasets/$DATASET_ID/runs" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg eid "$EXPERIMENT_ID" '{
"session_ids": [$eid],
"sort_params": {
"sort_by": "correctness",
"sort_order": "ASC"
}
}')"
After
curl -X POST "https://api.smith.langchain.com/api/v2/datasets/$DATASET_ID/experiment-runs" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg eid "$EXPERIMENT_ID" '{
"experiment_ids": [$eid],
"sort": {
"by": "feedback.correctness",
"order": "ASC"
}
}')"
import SmithdbRunsAddToQueueBeforePy from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-before-py.mdx';
import SmithdbRunsAddToQueueAfterPy from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-after-py.mdx';
import SmithdbRunsAddToQueueBeforeJs from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-before-js.mdx';
import SmithdbRunsAddToQueueAfterJs from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-after-js.mdx';
import SmithdbRunsAddToQueueBeforeKt from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-before-kt.mdx';
import SmithdbRunsAddToQueueAfterKt from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-after-kt.mdx';
import SmithdbRunsAddToQueueBeforeGo from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-before-go.mdx';
import SmithdbRunsAddToQueueAfterGo from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-after-go.mdx';
import SmithdbRunsAddToQueueBeforeSh from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-before-sh.mdx';
import SmithdbRunsAddToQueueAfterSh from '/snippets/code-samples/smithdb-migration/runs-add-to-queue-after-sh.mdx';
## 注解队列:添加运行
将运行添加到注解队列。基于SmithDB的路径会使用每个运行的完整查找键——即其ID加上 `session_id`(项目UUID)和 `start_time` 分区键——这样可以直接定位运行,而无需进行扫描。
<Note>
此方法保留在现有客户端上,而不是新的 `runs` v2 客户端,因此上面的[异常](/langsmith/smithdb-sdk-migration#exceptions)表不适用——错误处理保持不变。
</Note>
### 主要更改
#### 方法名
<Tabs>
<Tab title="Python">
无变化——`client.add_runs_to_annotation_queue()`。SmithDB路径由您传递的参数选择(参见下方的“输入”部分)。
请参阅[参考文档](https://reference.langchain.com/python/langsmith/client/Client/add_runs_to_annotation_queue)获取完整参数列表。
</Tab>
<Tab title="TypeScript">
无变化——`client.addRunsToAnnotationQueue()`。SmithDB路径由您传递的参数选择(参见下方的“输入”部分)。
请参阅[参考文档](https://reference.langchain.com/javascript/langsmith/client/Client/addRunsToAnnotationQueue)获取完整参数列表。
</Tab>
<Tab title="Java">
| 之前 | 之后 |
|--------|-------|
| `client.annotationQueues().runs().create()` | `client.annotationQueues().runs().createByKey()` |
请参阅[参考文档](https://javadoc.io/doc/com.langchain.smith/langsmith-java/latest/com/langchain/smith/services/blocking/annotationqueues/RunService.html)获取完整参数列表。
</Tab>
<Tab title="Go">
| 之前 | 之后 |
|--------|-------|
| `client.AnnotationQueues.Runs.New()` | `client.AnnotationQueues.Runs.NewByKey()` |
请参阅[参考文档](https://pkg.go.dev/github.com/langchain-ai/langsmith-go#AnnotationQueueRunService.NewByKey)获取完整参数列表。
</Tab>
<Tab title="cURL">
| 之前 | 之后 |
|--------|-------|
| `POST /api/v1/annotation-queues/{queue_id}/runs` | `POST /api/v1/annotation-queues/{queue_id}/runs/by-key` |
请参阅 [API 文档](/langsmith/smith-api/annotation-queues/add-runs-to-annotation-queue-by-key)获取完整参数列表。
</Tab>
</Tabs>
#### 输入
<Tabs>
<Tab title="Python">
<Warning>
SmithDB路径除了需要每个运行的 `run_id` 外,还需要 `session_id`(项目UUID)和 `start_time`。这些信息已存在于您获取的运行对象上(例如从 `client.list_runs()` 获取的)。
</Warning>
| 之前 (`run_ids`) | 之后 (`runs`) | 备注 |
|---|---|---|
| `run_ids: list[UUID \| str]` | *(已弃用)* | 旧路径。仍然有效并会调用 `/runs`,在服务器端解析每个运行。将在未来版本中移除 |
| *(不可用)* | `runs: Sequence[RunKey]` | **新的首选方式。** 每个 `RunKey` 是一个包含 `run_id`、`session_id` 和 `start_time` 的 `TypedDict` |
只能提供 `runs` 或 `run_ids` 中的一个;同时传递两者会引发 `LangSmithUserError`。
</Tab>
<Tab title="TypeScript">
<Warning>
SmithDB路径除了需要每个运行的 `runId` 外,还需要 `sessionId`(项目UUID)和 `startTime`。这些信息已存在于您获取的运行对象上(例如从 `client.listRuns()` 获取的)。
</Warning>
| 之前 (`string[]`) | 之后 (`RunKey[]`) | 备注 |
|---|---|---|
| `runs: string[]` | *(已弃用)* | 旧路径(运行ID字符串数组)。仍然有效并会调用 `/runs`。将在未来版本中移除 |
| *(不可用)* | `runs: RunKey[]` | **新的首选方式。** 每个 `RunKey` 是 `{ runId, sessionId, startTime }`;`startTime` 接受 `Date`、毫秒纪元或 ISO 字符串 |
两种形式都是相同的第二个位置参数;当您传递 `RunKey[]` 时,SDK 会选择 SmithDB 路径。
</Tab>
<Tab title="Java">
| 之前 (`RunCreateParams`) | 之后 (`RunCreateByKeyParams`) | 备注 |
|---|---|---|
| `.bodyOfRunsUuidArray(List<String>)` | *(已移除)* | 旧的请求体;仅包含运行ID |
| *(不可用)* | `.addBody(RunCreateByKeyParams.Body)` | 每个 `Body` 包含 `runId`、`sessionId` 和 `startTime` |
| `.queueId(String)` | `.queueId(String)` | 无变化 |
| `.extendTraceRetention(Boolean)` | `.extendTraceRetention(Boolean)` | 无变化的可选查询参数 |
</Tab>
<Tab title="Go">
| 之前 (`AnnotationQueueRunNewParams`) | 之后 (`AnnotationQueueRunNewByKeyParams`) | 备注 |
|---|---|---|
| `Body: AnnotationQueueRunNewParamsBodyRunsUuidArray` (`[]string`) | *(已移除)* | 旧的请求体;仅包含运行ID |
| *(不可用)* | `Body: []AnnotationQueueRunNewByKeyParamsBody` | 每个包含 `RunID`、`SessionID` 和 `StartTime` |
| *(不可用)* | `ExtendTraceRetention` | 可选查询参数 |
</Tab>
<Tab title="cURL">
<Warning>
`/runs/by-key` 的请求体是一个对象数组,而不是 ID 字符串数组。每个对象需要 `run_id`、`session_id`(项目UUID)和 `start_time`(RFC3339格式)。
</Warning>
| 之前 (`POST /runs` 请求体) | 之后 (`POST /runs/by-key` 请求体) | 备注 |
|---|---|---|
| `["<run-id>", ...]` | `[{"run_id", "session_id", "start_time"}]` | `session_id` 是项目UUID;`start_time` 是 RFC3339 格式 |
| `?extend_trace_retention` (查询参数) | `?extend_trace_retention` (查询参数) | 无变化的可选查询参数 |
</Tab>
</Tabs>
#### 响应
<Tabs>
<Tab title="Python">
无变化。`run_ids=` 和 `runs=` 都返回 `None`。
</Tab>
<Tab title="TypeScript">
无变化。两种形式都解析为 `void`。
</Tab>
<Tab title="Java">
`createByKey()` 返回 `List<RunCreateByKeyResponse>`——与 `create()` 返回的形状相同,包含 `id()`、`queueId()`、`runId()`、`addedAt()` 和 `lastReviewedTime()`。
</Tab>
<Tab title="Go">
`NewByKey()` 返回 `*[]AnnotationQueueRunNewByKeyResponse`——与 `New()` 返回的形状相同,包含 `ID`、`QueueID`、`RunID`、`AddedAt` 和 `LastReviewedTime`。
</Tab>
<Tab title="cURL">
无变化。`POST /runs/by-key` 返回创建的队列-运行记录数组(`id`、`queue_id`、`run_id`、`added_at`、`last_reviewed_time`),与 `POST /runs` 的形状相同。
</Tab>
</Tabs>
### 示例
#### 向队列添加运行
<Tabs>
<Tab title="Python">
`run_ids=` 接受一个简单的运行ID列表。`runs=` 接受每个运行的完整查找键——从您已有的运行对象上读取 `run_id`、`session_id` 和 `start_time`。
<Tabs sync={false}>
<Tab title="之前">
<SmithdbRunsAddToQueueBeforePy />
</Tab>
<Tab title="之后">
<SmithdbRunsAddToQueueAfterPy />
</Tab>
</Tabs>
</Tab>
<Tab title="TypeScript">
对于旧路径,传递运行ID字符串数组;或者传递基于您已有的运行对象构建的 `RunKey` 对象(`runId`、`sessionId`、`startTime`)数组。
<Tabs sync={false}>
<Tab title="之前">
<SmithdbRunsAddToQueueBeforeJs />
</Tab>
<Tab title="之后">
<SmithdbRunsAddToQueueAfterJs />
</Tab>
</Tabs>
</Tab>
<Tab title="Java">
`create()` 通过 `bodyOfRunsUuidArray` 接受运行ID。`createByKey()` 为每个运行接受一个包含 `runId`、`sessionId` 和 `startTime` 的 `Body`。
<Tabs sync={false}>
<Tab title="之前">
<SmithdbRunsAddToQueueBeforeKt />
</Tab>
<Tab title="之后">
<SmithdbRunsAddToQueueAfterKt />
</Tab>
</Tabs>
</Tab>
<Tab title="Go">
`New()` 通过 `AnnotationQueueRunNewParamsBodyRunsUuidArray` 接受运行ID。`NewByKey()` 为每个运行接受一个包含 `RunID`、`SessionID` 和 `StartTime` 的 `AnnotationQueueRunNewByKeyParamsBody`。
<Tabs sync={false}>
<Tab title="之前">
<SmithdbRunsAddToQueueBeforeGo />
</Tab>
<Tab title="之后">
<SmithdbRunsAddToQueueAfterGo />
</Tab>
</Tabs>
</Tab>
<Tab title="cURL">
`POST /runs` 接受运行ID字符串数组。`POST /runs/by-key` 接受对象数组,每个对象包含 `run_id`、`session_id` 和 `start_time`。
<Tabs sync={false}>
<Tab title="之前">
<SmithdbRunsAddToQueueBeforeSh />
</Tab>
<Tab title="之后">
<SmithdbRunsAddToQueueAfterSh />
</Tab>
</Tabs>
</Tab>
</Tabs>
import SmithdbPublicRunsBeforePy from '/snippets/code-samples/smithdb-migration/public-runs-before-py.mdx';
import SmithdbPublicRunsAfterPy from '/snippets/code-samples/smithdb-migration/public-runs-after-py.mdx';
import SmithdbPublicRunsBeforeJs from '/snippets/code-samples/smithdb-migration/public-runs-before-js.mdx';
import SmithdbPublicRunsAfterJs from '/snippets/code-samples/smithdb-migration/public-runs-after-js.mdx';
import SmithdbPublicRunsBeforeSh from '/snippets/code-samples/smithdb-migration/public-runs-before-sh.mdx';
import SmithdbPublicRunsAfterSh from '/snippets/code-samples/smithdb-migration/public-runs-after-sh.mdx';
## 分享和读取公共运行记录
分享一条追踪记录、移除其公共访问权限,或读取在公共共享追踪记录中的运行记录。v2 版本方法使用显式的 SmithDB 坐标,并返回选择驱动的运行对象。
公共读取方法不需要 LangSmith API 密钥。请将共享令牌视为机密,因为任何拥有该令牌的人都可以读取共享的追踪记录。
### 主要变更
#### 方法名称
<Tabs>
<Tab title="Python">
| 之前 | 之后 |
|---|---|
| `client.share_run()` | `client.runs.share.create()` |
| `client.unshare_run()` | `client.runs.share.delete()` |
| `client.list_shared_runs()` | `client.public.runs.query()` |
| `client.read_shared_run()` | `client.public.runs.retrieve()` |
| `client.read_run_shared_link()` | `client.runs.retrieve(selects=["SHARE_URL"])` |
<Note>
v2 版本的资源方法是异步的。调用时需要使用 `await`。
</Note>
</Tab>
<Tab title="TypeScript">
| 之前 | 之后 |
|---|---|
| `client.shareRun()` | `client.runs.share.create()` |
| `client.unshareRun()` | `client.runs.share.delete()` |
| `client.listSharedRuns()` | `client.public.runs.query()` |
| `client.listSharedRuns({ runIds: [...] })` | `client.public.runs.retrieve()` |
| `client.readRunSharedLink()` | `client.runs.retrieve({ selects: ["SHARE_URL"] })` |
TypeScript 没有直接等同于 Python `read_shared_run` 的方法。经过过滤的 `listSharedRuns` 调用将迁移到单点读取方法。
</Tab>
<Tab title="Java">
Java SDK 没有需要迁移的旧版便捷方法。请使用 [`ShareService`](https://javadoc.io/doc/com.langchain.smith/langsmith-java/latest/com/langchain/smith/services/blocking/runs/ShareService.html) 和公共 [`RunService`](https://javadoc.io/doc/com.langchain.smith/langsmith-java/latest/com/langchain/smith/services/blocking/public_/RunService.html) 进行 v2 访问。Kotlin 使用 Java SDK;没有单独的 Kotlin 参考网站。
</Tab>
<Tab title="Go">
Go SDK 没有需要迁移的旧版便捷方法。请使用 [`RunShareService`](https://pkg.go.dev/github.com/langchain-ai/langsmith-go#RunShareService) 和 [`PublicRunService`](https://pkg.go.dev/github.com/langchain-ai/langsmith-go#PublicRunService) 进行 v2 访问。
</Tab>
<Tab title="cURL">
| 操作 | 之前 | 之后 |
|---|---|---|
| 分享 | `PUT /api/v1/runs/{run_id}/share` | `POST /api/v2/runs/{run_id}/share` |
| 取消分享 | `DELETE /api/v1/runs/{run_id}/share` | `DELETE /api/v2/runs/{trace_id}/share` |
| 查询公共运行记录 | `POST /api/v1/public/{share_token}/runs/query` | `POST /api/v2/public/{share_token}/runs/query` |
| 检索公共运行记录 | `GET /api/v1/public/{share_token}/run/{run_id}` | `GET /api/v2/public/{share_token}/run/{run_id}` |
| 读取共享状态 | `GET /api/v1/runs/{run_id}/share` | `GET /api/v2/runs/{run_id}?selects=SHARE_URL` |
旧版 `GET /api/v1/public/{share_token}/run` 端点(不带运行 ID)没有直接的 v2 等效项。
</Tab>
</Tabs>
#### 分享和取消分享参数
<Tabs>
<Tab title="Python">
- `runs.share.create` 接受运行 ID 作为其位置参数。传递 `session_id`(追踪项目 UUID)和 `trace_id`(根追踪 UUID)。
- `runs.share.delete` 接受根追踪 ID,而不是任意的子运行 ID。传递追踪项目 UUID 作为 `session_id`。
- `share_id` 已被移除。服务器会生成共享令牌。
</Tab>
<Tab title="TypeScript">
- `runs.share.create` 接受运行 ID 作为其位置参数。在选项对象中传递 `session_id` 和根 `trace_id`。
- `runs.share.delete` 接受根追踪 ID 和包含 `session_id` 的选项对象。
- `shareId` 已被移除。服务器会生成共享令牌。
</Tab>
<Tab title="cURL">
- v2 分享请求体包含 `session_id` 和 `trace_id`。
- v2 取消分享路径标识根追踪记录。其请求体包含 `session_id`。
- v2 取消分享操作是幂等的,返回 `204 No Content`。
</Tab>
</Tabs>
尽管生成的参数类型可能将这些坐标标记为可选,但在分享时请提供 `session_id` 和 `trace_id`,在取消分享时请提供 `session_id`。SmithDB 使用这些坐标进行查找。
#### 公共读取参数
- `public.runs.query` 接受共享令牌和一个 `selects` 列表。该令牌将查询范围限定在完整的共享追踪记录中。旧版的运行 ID 过滤器和游标响应已被移除。
- `public.runs.retrieve` 需要运行 ID、共享令牌、精确的运行 `start_time` 和一个 `selects` 列表。从 `public.runs.query` 获取精确的存储开始时间。
- 公共单点读取仅返回选定的字段。下面的示例使用 `ID`、`NAME`、`RUN_TYPE`、`STATUS` 和 `START_TIME`。
- 要检索经过身份验证的运行的公共 URL,请使用 `selects=["SHARE_URL"]` 调用 `runs.retrieve`,然后读取 `run.share_url`。提供 `start_time` 可以为 SmithDB 提供最高效的查找。
请勿从 API 源构建公共 URL。检索 `share_url` 使用部署配置的应用程序源,适用于云部署和自托管部署。
#### 响应
| 操作 | 之前 | 之后 |
|---|---|---|
| 分享 | 运行 ID、共享追踪 ID 和共享令牌 | `share_token` |
| 取消分享 | `{"message": "Run unshared"}` | `204 No Content` |
| 查询公共运行记录 | `runs` 和 `cursors` | `items` |
| 检索公共运行记录 | 完整的旧版运行对象 | 选择驱动的运行对象 |
| 读取共享状态 | 共享状态对象或 `null` | 已分享时返回带有 `share_url` 的运行对象 |
### 示例
示例在单点读取之前查询公共追踪记录,因为 `public.runs.retrieve` 需要运行精确的存储 `start_time`。
<Tabs>
<Tab title="Python">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbPublicRunsBeforePy />
</Tab>
<Tab title="之后">
<SmithdbPublicRunsAfterPy />
</Tab>
</Tabs>
</Tab>
<Tab title="TypeScript">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbPublicRunsBeforeJs />
</Tab>
<Tab title="之后">
<SmithdbPublicRunsAfterJs />
</Tab>
</Tabs>
</Tab>
<Tab title="cURL">
<Tabs sync={false}>
<Tab title="之前">
<SmithdbPublicRunsBeforeSh />
</Tab>
<Tab title="之后">
<SmithdbPublicRunsAfterSh />
</Tab>
</Tabs>
</Tab>
</Tabs>
反馈:创建
为一次运行创建反馈(评分、修正或评论)。主要变更
必需参数
方法名和端点没有变化。仅会话(项目)ID 要求有所改变。- Python
- TypeScript
- Java
- Go
- cURL
create_feedback 现在需要 session_id,即拥有该运行的项目(会话)的 UUID。此前该参数是可选的。| 之前 | 之后 | 备注 |
|---|---|---|
session_id(可选) | session_id(必需) | 拥有该运行的项目的 UUID;如果你尚未拥有它,可通过 client.read_project() 获取 |
client.createFeedback 现在需要 sessionId,即拥有该运行的项目(会话)的 UUID。此前该参数是可选的。| 之前 | 之后 | 备注 |
|---|---|---|
sessionId(可选) | sessionId(必需) | 拥有该运行的项目的 UUID;如果你尚未拥有它,可通过 client.readProject() 获取 |
FeedbackCreateSchema.sessionId() 现在是必需的。此前该参数是可选的。| 之前 | 之后 | 备注 |
|---|---|---|
sessionId()(可选) | sessionId()(必需) | 拥有该运行的项目的 UUID;如果你尚未拥有它,可通过 client.sessions().list() 获取 |
FeedbackCreateSchemaParam.SessionID 现在是必需的。此前该参数是可选的。| 之前 | 之后 | 备注 |
|---|---|---|
SessionID(可选) | SessionID(必需) | 拥有该运行的项目的 UUID;如果你尚未拥有它,可通过 client.Sessions.List() 获取 |
POST /api/v1/feedback 现在需要在请求体中包含 session_id 字段。此前该字段是可选的。| 之前 | 之后 | 备注 |
|---|---|---|
session_id(可选) | session_id(必需) | 拥有该运行的项目的 UUID;如果你尚未拥有它,可通过 GET /api/v1/sessions 获取 |
示例
创建反馈时提供 session_id
- Python
- TypeScript
- Java
- Go
- cURL
create_feedback 现在除了 run_id 外还需要 session_id。- 之前
- 之后
Before
from langsmith import Client
client = Client()
run_id = "<run-id>"
client.create_feedback(
run_id=run_id,
key="user_feedback",
score=1,
)
以下是按照您的要求处理后的中文翻译版本。该代码块内不包含任何需要翻译的自然语言注释或说明,因此代码部分保持原样:
After
from langsmith import Client
client = Client()
run_id = "<run-id>"
session_id = "<session-id>"
client.create_feedback(
run_id=run_id,
key="user_feedback",
score=1,
session_id=session_id,
)
client.createFeedback 现在除了 runId 外还需要 sessionId。- 之前
- 之后
Before
import { Client } from "langsmith";
const client = new Client();
let runId = "<run-id>";
await client.createFeedback(runId, "user_feedback", {
score: 1,
});
After
import { Client } from "langsmith";
const client = new Client();
let runId = "<run-id>";
let sessionId = "<session-id>";
await client.createFeedback(runId, "user_feedback", {
score: 1,
sessionId,
});
.create() 现在除了 .runId() 外还需要 .sessionId()。- 之前
- 之后
Before
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.feedback.FeedbackCreateSchema
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
var runId = "<run-id>"
client.feedback().create(
FeedbackCreateSchema.builder()
.runId(runId)
.key("用户反馈")
.score(1.0)
.build()
)
After
import com.langchain.smith.client.LangsmithClient
import com.langchain.smith.client.okhttp.LangsmithOkHttpClient
import com.langchain.smith.models.feedback.FeedbackCreateSchema
val client: LangsmithClient = LangsmithOkHttpClient.fromEnv()
var runId = "<run-id>"
var sessionId = "<session-id>"
client.feedback().create(
FeedbackCreateSchema.builder()
.runId(runId)
.key("user_feedback")
.score(1.0)
.sessionId(sessionId)
.build()
)
Feedback.New 现在除了 RunID 外还需要 SessionID。- 之前
- 之后
Before
package main
import (
"context"
"github.com/langchain-ai/langsmith-go"
"github.com/langchain-ai/langsmith-go/shared"
)
ctx := context.Background()
client := langsmith.NewClient()
runID := "<run-id>"
var err error
_, err = client.Feedback.New(ctx, langsmith.FeedbackNewParams{
FeedbackCreateSchema: langsmith.FeedbackCreateSchemaParam{
RunID: langsmith.F(runID),
Key: langsmith.F("user_feedback"),
Score: langsmith.F[langsmith.FeedbackCreateSchemaScoreUnionParam](shared.UnionFloat(1.0)),
},
})
After
package main
import (
"context"
"github.com/langchain-ai/langsmith-go"
"github.com/langchain-ai/langsmith-go/shared"
)
ctx := context.Background()
client := langsmith.NewClient()
runID := "<run-id>"
sessionID := "<session-id>"
var err error
_, err = client.Feedback.New(ctx, langsmith.FeedbackNewParams{
FeedbackCreateSchema: langsmith.FeedbackCreateSchemaParam{
RunID: langsmith.F(runID),
Key: langsmith.F("用户反馈"),
Score: langsmith.F[langsmith.FeedbackCreateSchemaScoreUnionParam](shared.UnionFloat(1.0)),
SessionID: langsmith.F(sessionID),
},
})
POST /api/v1/feedback 现在除了 run_id 外还需要 session_id 字段。- 之前
- 之后
RUN_ID="<run-id>"
curl -X POST "https://api.smith.langchain.com/api/v1/feedback" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg run "$RUN_ID" '{"run_id": $run, "key": "user_feedback", "score": 1}')"
RUN_ID="<run-id>"
SESSION_ID="<session-id>"
curl -X POST "https://api.smith.langchain.com/api/v1/feedback" \
-H "x-api-key: $LANGSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg run "$RUN_ID" --arg session "$SESSION_ID" '{"run_id": $run, "key": "user_feedback", "score": 1, "session_id": $session}')"
异常处理变化
- Python
- TypeScript
- Java
- Go
- cURL
基于 SmithDB 的方法会抛出新的异常类,而不是旧的
langsmith.utils 异常类。迁移前 (langsmith.utils) | 迁移后 (langsmith) | 备注 |
|---|---|---|
LangSmithError | LangsmithError | SDK 的基础异常类;大小写发生变化 |
LangSmithAPIError | InternalServerError | 5xx 错误 |
LangSmithRequestTimeout | APITimeoutError | 请求超时时抛出 |
LangSmithUserError | (已移除) | 无直接等效项。403 组织范围密钥的场景现在抛出 PermissionDeniedError;客户端参数验证现在抛出标准的 ValueError 或 TypeError |
LangSmithRateLimitError | RateLimitError | 429 错误;名称未变 |
LangSmithAuthError | AuthenticationError | 401 错误 |
LangSmithNotFoundError | NotFoundError | 404 错误;名称未变 |
LangSmithConflictError | ConflictError | 409 错误;名称未变 |
LangSmithConnectionError | APIConnectionError | 客户端无法连接到 API 时抛出 |
LangSmithExceptionGroup | (已移除) | 无等效项 |
| (不适用) | APIError | 新增:所有 API 相关错误的基类,具有 message、request 和 body 属性 |
| (不适用) | APIStatusError | 新增:所有 4xx/5xx 状态错误的基类 |
| (不适用) | BadRequestError | 新增:400 错误 |
| (不适用) | PermissionDeniedError | 新增:403 错误 |
| (不适用) | UnprocessableEntityError | 新增:422 错误 |
| (不适用) | APIResponseValidationError | 新增:当响应与预期模式不匹配时抛出 |
基于 SmithDB 的方法会抛出新的异常类,而不是普通的
Error。迁移前 (普通 Error) | 迁移后 (langsmith) | 备注 |
|---|---|---|
| (不适用) | LangsmithError | 所有 SDK 错误的基类 |
| (不适用) | InternalServerError | 5xx 错误 |
| (不适用) | APIConnectionTimeoutError | 请求超时时抛出 |
| (不适用) | RateLimitError | 429 错误 |
| (不适用) | AuthenticationError | 401 错误 |
| (不适用) | NotFoundError | 404 错误 |
| (不适用) | ConflictError | 409 错误 |
| (不适用) | APIConnectionError | 客户端无法连接到 API 时抛出 |
| (不适用) | APIError | 所有 API 相关错误的基类,具有 status、headers 和 error 属性 |
| (不适用) | BadRequestError | 400 错误 |
| (不适用) | PermissionDeniedError | 403 错误 |
| (不适用) | UnprocessableEntityError | 422 错误 |
| (不适用) | APIUserAbortError | 当请求通过 AbortController 中止时抛出 |
无变化。此次迁移不影响错误处理。
无变化。此次迁移不影响错误处理。
无变化。此次迁移不影响错误处理。
已停止支持
以下方法已停止支持。它们调用了已退役的/feedback/formulas 端点,该端点在复合反馈 v2 上返回 410 Gone,并计划于 2026-08-20 移除。复合分数现在作为复合评估器进行管理,它将复合分数实现为代码评估器加上运行规则。没有 SDK 替代方案。
反馈公式方法
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

