规模化构建 Agent 会引入大量基于使用量的成本,这些成本难以追踪。LangSmith 会自动记录主要提供商的 LLM Token 使用量和成本,也允许您为任何其他组件提交自定义成本数据。
这为您提供了整个应用程序成本的单一统一视图,使您可以轻松监控、理解和调试支出。
在 LangSmith UI 中查看成本
在 LangSmith UI,您可以通过三种方式探索使用量和支出:作为单个追踪中的明细,作为项目统计中的聚合指标,以及在仪表板中。
Token 和成本明细
UI 将 Token 使用量和成本分为三个类别:
- 输入:发送给模型的提示词中的 Token。子类型包括:缓存读取、文本 Token、图像 Token 等。
- 输出:模型在响应中生成的 Token。子类型包括:推理 Token、文本 Token、图像 Token 等。
- 其他:工具调用、检索步骤或任何自定义运行的费用。
您可以通过将鼠标悬停在 UI 中的费用部分来查看详细明细。如果可用,每个部分还会按子类型进一步分类。
您可以在 LangSmith UI 中查看这些细分:
在追踪树中
追踪树显示令牌使用和成本的最详细视图(对于单个追踪)。它显示整个追踪的总使用量、每个父级运行的聚合值,以及每个子级运行的令牌和成本细分。
打开追踪项目中的任何运行以查看其追踪树。
在项目统计中
项目统计面板显示项目中所有追踪的总令牌使用量和成本。
在仪表板中
仪表板帮助您探索成本和令牌使用趋势。 预构建仪表板 显示追踪项目的总成本以及按输入和输出令牌的的成本细分。
您还可以在中配置自定义成本追踪图表 自定义仪表板.
成本追踪
您可以通过两种方式追踪成本:
- **自动**:根据 LLM 调用的令牌数量和模型价格计算。
- **手动**:直接在任意运行上指定,包括非LLM类型。
| 方法 | 运行类型:LLM | 运行类型:其他 |
|---|---|---|
| **自动** | <ul><li>使用 LangChain</li><li>使用 LangChain 将 LLM 调用追踪到 OpenAI、Anthropic 或遵循 OpenAI 兼容格式的模型 @traceable</li><li> 使用 LangSmith 包装器调用 OpenAI or Anthropic</li><li>对于其他模型提供商,请阅读 令牌和成本信息指南</li></ul> | 不适用。 |
| **手动** | 如果LLM调用成本是非线性的(例如遵循自定义成本函数) | 发送任何运行类型的成本,例如工具调用、检索步骤 |
LLM调用:基于令牌数量自动跟踪成本
要根据令牌使用量自动计算成本,您需要提供 **令牌数量**、 **模型和提供商**以及 **模型价格**.
1. 发送令牌数量。许多模型会在响应中包含令牌数量。您必须提取此信息并使用以下方法之一将其包含在运行中: - 在运行的元数据中设置 usage_metadata 字段。这种方法的优点是无需更改被追踪函数的运行时输出:
from langsmith import traceable, get_current_run_tree
inputs = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "I'd like to book a table for two."},
]
@traceable(
run_type="llm",
metadata={"ls_provider": "my_provider", "ls_model_name": "my_model"}
)
def chat_model(messages: list):
# Imagine this is the real model output format your application expects
assistant_message = {
"role": "assistant",
"content": "Sure, what time would you like to book the table for?"
}
# Token usage you compute or receive from the provider
token_usage = {
"input_tokens": 27,
"output_tokens": 13,
"total_tokens": 40,
"input_token_details": {"cache_read": 10}
}
# Attach token usage to the LangSmith run
run = get_current_run_tree()
run.set(usage_metadata=token_usage)
return assistant_message
chat_model(inputs)
const inputs = [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "I'd like to book a table for two." },
];
const chatModel = traceable(
async ({ messages }) => {
// The output your application expects
const assistantMessage = {
role: "assistant",
content: "Sure, what time would you like to book the table for?",
};
// Token usage you compute or receive from the provider
const tokenUsage = {
input_tokens: 27,
output_tokens: 13,
total_tokens: 40,
input_token_details: { cache_read: 10 },
};
// Attach usage to the LangSmith run
const runTree = getCurrentRunTree();
runTree.metadata.usage_metadata = tokenUsage;
return assistantMessage;
},
{
run_type: "llm",
name: "chat_model",
metadata: {
ls_provider: "my_provider",
ls_model_name: "my_model",
},
}
);
await chatModel({ messages: inputs });
Java 和 Kotlin 示例使用专用执行器。关闭执行器并等待终止可确保在进程退出前完成后台追踪提交。
- - 在追踪函数的输出中返回一个
usage_metadata字段。包含usage_metadata键在追踪函数返回的对象内。LangSmith 会从输出中提取它:
from langsmith import traceable
inputs = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "I'd like to book a table for two."},
]
output = {
"choices": [
{
"message": {
"role": "assistant",
"content": "Sure, what time would you like to book the table for?"
}
}
],
"usage_metadata": {
"input_tokens": 27,
"output_tokens": 13,
"total_tokens": 40,
"input_token_details": {"cache_read": 10}
},
}
@traceable(
run_type="llm",
metadata={"ls_provider": "my_provider", "ls_model_name": "my_model"}
)
def chat_model(messages: list):
return output
chat_model(inputs)
const messages = [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "I'd like to book a table for two." }
];
const output = {
choices: [
{
message: {
role: "assistant",
content: "Sure, what time would you like to book the table for?",
},
},
],
usage_metadata: {
input_tokens: 27,
output_tokens: 13,
total_tokens: 40,
},
};
const chatModel = traceable(
async ({
messages,
}: {
messages: { role: string; content: string }[];
model: string;
}) => {
return output;
},
{
run_type: "llm",
name: "chat_model",
metadata: {
ls_provider: "my_provider",
ls_model_name: "my_model"
}
}
);
await chatModel({ messages });
在任何一种情况下,使用元数据应包含以下 LangSmith 识别的字段子集:
Usage Metadata Schema and Cost Calculation
以下字段在 usage_metadata 字典中由 LangSmith 识别。您可以查看完整的 Python 类型 or TypeScript 接口 directly.
模型输入中使用的令牌数量。所有输入令牌类型的总和。
模型响应中使用的令牌数量。所有输出令牌类型的总和。
输入和输出中使用的令牌数量。可选,可以推断。是输入_令牌 + 输出_tokens.
输入令牌类型的细分。键是令牌类型字符串,值是计数。例如 {"cache_read": 5}.
已知字段包括: audio, text, image, cache_read, cache_creation, cache_read_over_200k (Gemini)、 ephemeral_5m_input_tokens, ephemeral_1h_input_tokens (Anthropic 临时缓存层级)。根据模型或提供商的不同,可能还有其他字段。
输出token类型的细分。键是token类型字符串,值是计数。示例 {"reasoning": 5}.
已知字段包括: audio, text, image, reasoning。根据模型或提供商的不同,可能存在其他字段。
输入token的成本。
输出token的成本。
Token的成本。可选,可以推断。输入之和_成本 + 输出_cost.
输入成本的详细信息。键是token类型字符串,值是成本金额。
输出成本的详细信息。键是token类型字符串,值是成本金额。
成本计算
The cost for a run is computed greedily from most-to-least specific token type. Suppose you set a price of \$2 per 1M input tokens with a detailed price of \$1 per 1M cache_read input tokens, and \$3 per 1M output tokens. If you uploaded the following usage metadata:
{
"input_tokens": 20,
"input_token_details": {"cache_read": 5},
"output_tokens": 10,
"total_tokens": 30,
}
然后,token成本将按如下方式计算:
# Notice that LangSmith computes the cache_read cost and then for any
# remaining input_tokens, the default input price is applied.
input_cost = 5 * 1e-6 + (20 - 5) * 2e-6 # 3.5e-5
output_cost = 10 * 3e-6 # 3e-5
total_cost = input_cost + output_cost # 6.5e-5
- 指定模型名称。使用自定义模型时,需要在 运行的元数据 中指定以下字段,以便将token计数与成本关联。在查看traces和过滤时,提供这些元数据字段也有助于识别模型。
- -
ls_provider:模型的提供商,例如"openai"、"anthropic" - -
ls_model_name:模型的名称,例如"gpt-5.4-mini"、"claude-3-opus-20240229"
- 设置模型价格。LangSmith使用其 模型定价表 将模型名称映射到每token价格以从token计数计算成本。
对于具有不同token类型不同定价的模型(例如多模态或缓存token),您可以为每种token类型指定价格细分。将鼠标悬停在 **...** 旁边的 **输入价格** 和 **输出价格** 条目上会显示按token类型的价格细分。
创建新的或修改现有的模型价格条目
要修改默认模型价格,请使用与默认条目相同的模型、提供商和匹配模式创建一个新条目。
要在模型定价映射中创建新条目,请点击 **+ 模型** 右上角的按钮。
在这里,您可以指定以下字段:
- 模型名称:模型的人类可读名称。
- 输入价格:模型的每1M输入token的成本。这个数字乘以prompt中的token数量来计算prompt成本。
- 输入价格细分 (可选):每种不同类型输入token的价格细分,例如,
cache_read,video,audio. - 输出价格:模型的每1M输出token的成本。这个数字乘以completion中的token数量来计算completion成本。
- 输出价格细分 (可选):每种不同类型输出令牌的价格明细,例如:
reasoning,image等。 - 模型激活日期 (可选):价格生效的日期。只有在此日期之后运行的才会应用此模型价格。
- 匹配模式:用于匹配模型名称的正则表达式模式。用于匹配
ls_model_name中的值。 - 提供商 (可选):模型的提供商。如果指定,将与
ls_provider中的值进行匹配。
一旦设置了模型价格映射,LangSmith 将根据 LLM 调用中提供的令牌计数自动计算和汇总追踪的基于令牌的成本。
LLM 调用:直接发送成本
Gemini 2.5 Pro Preview 和 Gemini 2.5 Pro 使用分步成本函数,LangSmith 默认支持。对于任何其他具有非线性定价的模型,请在客户端计算成本并将其作为 usage_metadata 发送,如下代码所示:
from langsmith import traceable, get_current_run_tree
inputs = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "I'd like to book a table for two."},
]
@traceable(
run_type="llm",
metadata={"ls_provider": "my_provider", "ls_model_name": "my_model"}
)
def chat_model(messages: list):
llm_output = {
"choices": [
{
"message": {
"role": "assistant",
"content": "Sure, what time would you like to book the table for?"
}
}
],
"usage_metadata": {
# Specify cost (in dollars) for the inputs and outputs
"input_cost": 1.1e-6,
"input_cost_details": {"cache_read": 2.3e-7},
"output_cost": 5.0e-6,
},
}
run = get_current_run_tree()
run.set(usage_metadata=llm_output["usage_metadata"])
return llm_output["choices"][0]["message"]
chat_model(inputs)
const messages = [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "I'd like to book a table for two." }
];
const chatModel = traceable(
async (messages: { role: string; content: string }[]) => {
const llmOutput = {
choices: [
{
message: {
role: "assistant",
content: "Sure, what time would you like to book the table for?",
},
},
],
// Specify cost (in dollars) for the inputs and outputs
usage_metadata: {
input_cost: 1.1e-6,
input_cost_details: { cache_read: 2.3e-7 },
output_cost: 5.0e-6,
},
};
// Attach usage metadata to the run
const runTree = getCurrentRunTree();
runTree.metadata.usage_metadata = llmOutput.usage_metadata;
// Return only the assistant message
return llmOutput.choices[0].message;
},
{
run_type: "llm",
name: "chat_model",
metadata: {
ls_provider: "my_provider",
ls_model_name: "my_model",
},
}
);
await chatModel(messages);
其他运行:发送成本
您还可以为任何非 LLM 运行(如工具调用)发送成本信息。请在 total_cost 字段中指定成本 usage_metadata:
from langsmith import traceable, get_current_run_tree
# Example tool: get_weather
@traceable(run_type="tool", name="get_weather")
def get_weather(city: str):
# Your tool logic goes here
result = {
"temperature_f": 68,
"condition": "sunny",
"city": city,
}
# Cost for this tool call (computed however you like)
tool_cost = 0.0015
# Attach usage metadata to the LangSmith run
run = get_current_run_tree()
run.set(usage_metadata={"total_cost": tool_cost})
# Return only the actual tool result (no usage info)
return result
tool_response = get_weather("San Francisco")
// Example tool: get_weather
const getWeather = traceable(
async ({ city }) => {
// Your tool logic goes here
const result = {
temperature_f: 68,
condition: "sunny",
city,
};
// Cost for this tool call (computed however you like)
const toolCost = 0.0015;
// Attach usage metadata to the LangSmith run
const runTree = getCurrentRunTree();
runTree.metadata.usage_metadata = {
total_cost: toolCost,
};
// Return only the actual tool result (no usage info)
return result;
},
{
run_type: "tool",
name: "get_weather",
}
);
const toolResponse = await getWeather({ city: "San Francisco" });
或者,将 usage_metadata 直接包含在追踪函数的返回值中:
from langsmith import traceable
# Example tool: get_weather
@traceable(run_type="tool", name="get_weather")
def get_weather(city: str):
# Your tool logic goes here
result = {
"temperature_f": 68,
"condition": "sunny",
"city": city,
}
# Attach tool call costs here
return {
**result,
"usage_metadata": {
"total_cost": 0.0015, # <-- cost for this tool call
},
}
tool_response = get_weather("San Francisco")
// Example tool: get_weather
const getWeather = traceable(
async ({ city }) => {
// Your tool logic goes here
const result = {
temperature_f: 68,
condition: "sunny",
city,
};
// Attach tool call costs here
return {
...result,
usage_metadata: {
total_cost: 0.0015, // <-- cost for this tool call
},
};
},
{
run_type: "tool",
name: "get_weather",
}
);
const toolResponse = await getWeather({ city: "San Francisco" });