0

0

在LangChain.js中高效追踪OpenAI模型令牌消耗与成本

聖光之護

聖光之護

发布时间:2025-11-24 16:16:02

|

667人浏览过

|

来源于php中文网

原创

在langchain.js中高效追踪openai模型令牌消耗与成本

本文旨在解决LangChain.js开发者在监控OpenAI模型令牌使用量和相关成本时遇到的挑战,尤其是在缺乏Python中`get_openai_callback()`直接对应功能的情况下。文章将详细介绍如何通过利用`ChatOpenAI`模型中的`handleLLMEnd`回调函数,精确地追踪每次模型运行的提示令牌、完成令牌及总令牌消耗,从而实现更精细的成本管理和性能分析。

在开发基于LangChain.js和OpenAI的项目时,准确追踪大型语言模型(LLM)的令牌消耗是优化成本和分析性能的关键一环。与LangChain Python框架中提供便捷的get_openai_callback()方法不同,LangChain.js目前并未提供一个直接的、等价的API来轻松获取每次链运行的令牌使用和成本信息,这给许多开发者带来了困扰。本文将详细阐述一种有效的方法,通过利用LangChain.js中LLM回调机制,实现对OpenAI模型令牌消耗的精确监控。

核心方法:利用handleLLMEnd回调函数

LangChain.js提供了强大的回调系统,允许开发者在LLM生命周期的不同阶段注入自定义逻辑。对于追踪令牌消耗,handleLLMEnd回调函数是理想的选择。这个函数会在每次LLM调用结束时被触发,并提供包含令牌使用信息的output参数。

Favird No-Code Tools
Favird No-Code Tools

无代码工具的聚合器

下载

实现步骤

  1. 导入ChatOpenAI: 确保您正在使用langchain/chat_models/openai模块中的ChatOpenAI类,因为目前观察到此方法在ChatOpenAI上表现最为稳定,尤其是在特定模型版本下。
  2. 定义令牌计数器: 初始化几个变量来累计不同类型的令牌消耗,例如totalCompletionTokens、totalPromptTokens和totalExecutionTokens。
  3. 配置callbacks属性: 在实例化ChatOpenAI时,通过callbacks属性传入一个包含回调函数的数组。
  4. 实现handleLLMEnd: 在回调对象中,定义handleLLMEnd方法。此方法接收output、runId等参数。关键在于从output.llmOutput?.tokenUsage中提取completionTokens、promptTokens和totalTokens。
  5. 累加令牌: 将提取到的令牌数量累加到预定义的计数器中。

示例代码

以下是实现令牌追踪的完整代码示例:

import { ChatOpenAI } from 'langchain/chat_models/openai';
import { HumanMessage } from 'langchain/schema';

// 定义全局变量来累积令牌使用量
let totalCompletionTokens = 0;
let totalPromptTokens = 0;
let totalExecutionTokens = 0;

// 实例化ChatOpenAI模型,并配置回调函数
const llm = new ChatOpenAI({
    // 配置回调数组
    callbacks: [
      {
        // handleLLMEnd在LLM调用结束后触发
        handleLLMEnd: (output, runId, parentRunId?, tags?) => {
          // 从output中安全地提取tokenUsage信息
          const { completionTokens, promptTokens, totalTokens } = output.llmOutput?.tokenUsage || {};

          // 累加令牌数量,确保处理undefined情况
          totalCompletionTokens += completionTokens ?? 0;
          totalPromptTokens += promptTokens ?? 0;
          totalExecutionTokens += totalTokens ?? 0;

          console.log(`--- LLM Run ID: ${runId} ---`);
          console.log(`Prompt Tokens: ${promptTokens ?? 0}`);
          console.log(`Completion Tokens: ${completionTokens ?? 0}`);
          console.log(`Total Tokens for this run: ${totalTokens ?? 0}`);
          console.log(`Current Accumulated Total Tokens: ${totalExecutionTokens}`);
        },
      },
    ],
    // 推荐使用特定的模型版本,例如 'gpt-3.5-turbo-0613'
    // 注意:某些模型或版本可能存在令牌统计不准确的问题
    modelName: 'gpt-3.5-turbo-0613', 
    // 其他OpenAI API参数,例如 temperature, openAIApiKey等
    temperature: 0.7,
    openAIApiKey: process.env.OPENAI_API_KEY, // 确保从环境变量获取API Key
});

// 示例:执行一次LLM调用
async function runExampleChat() {
    console.log("Starting LLM call...");
    const response = await llm.call([
        new HumanMessage("请用一句话介绍一下大型语言模型。"),
    ]);
    console.log("LLM Response:", response.content);
    console.log("\n--- Final Token Usage Summary ---");
    console.log(`Total Prompt Tokens Across All Runs: ${totalPromptTokens}`);
    console.log(`Total Completion Tokens Across All Runs: ${totalCompletionTokens}`);
    console.log(`Total Execution Tokens Across All Runs: ${totalExecutionTokens}`);

    // 重置计数器以便进行下一次独立测试(可选)
    totalCompletionTokens = 0;
    totalPromptTokens = 0;
    totalExecutionTokens = 0;
}

// 调用示例函数
runExampleChat().catch(console.error);

// 示例:执行另一次LLM调用
async function runAnotherExampleChat() {
    console.log("\nStarting another LLM call...");
    const response = await llm.call([
        new HumanMessage("解释一下云计算的优势。"),
    ]);
    console.log("LLM Response:", response.content);
    console.log("\n--- Final Token Usage Summary ---");
    console.log(`Total Prompt Tokens Across All Runs: ${totalPromptTokens}`);
    console.log(`Total Completion Tokens Across All Runs: ${totalCompletionTokens}`);
    console.log(`Total Execution Tokens Across All Runs: ${totalExecutionTokens}`);
}

// 可以在适当的时机调用 runAnotherExampleChat()
// setTimeout(() => runAnotherExampleChat().catch(console.error), 3000);

代码解析

  • output.llmOutput?.tokenUsage: 这是获取令牌使用信息的关键路径。llmOutput是一个可选属性,其中包含LLM的详细输出信息,而tokenUsage则是一个对象,包含了completionTokens(模型生成的令牌)、promptTokens(输入给模型的令牌)和totalTokens(总令牌)。
  • ?? 0: 使用空值合并运算符确保即使tokenUsage属性或其子属性为undefined,也能安全地将其视为0,避免计算错误。
  • modelName: 'gpt-3.5-turbo-0613': 这是一个重要的注意事项。根据社区反馈,在LangChain.js的某些版本(如0.0.116)中,令牌统计功能在使用ChatOpenAI和特定模型(如gpt-3.5-turbo-0613)时更为可靠。使用其他LLM类或模型可能无法正确返回令牌信息,这可能是一个框架特性或潜在的bug。

注意事项与成本计算

  1. 模型兼容性: 强烈建议使用ChatOpenAI类,并尝试使用如gpt-3.5-turbo-0613或更新的聊天模型版本。如果遇到令牌统计不准确的问题,首先检查所使用的LLM类和模型版本。
  2. 全局计数器: 示例中使用了全局变量来累积令牌。在实际生产环境中,您可能需要更复杂的管理方式,例如将这些计数器封装在一个服务或类中,或者与日志系统、监控系统集成。
  3. 成本计算: 一旦获取了promptTokens和completionTokens,就可以根据OpenAI的官方定价模型来计算成本。OpenAI通常会为输入(prompt)和输出(completion)令牌设定不同的费率。
    • 例如,如果Prompt Token价格为P美元/千令牌,Completion Token价格为C美元/千令牌,则总成本可以计算为: Cost = (totalPromptTokens / 1000) * P + (totalCompletionTokens / 1000) * C 请务必查阅OpenAI的最新定价页面以获取准确的费率。
  4. 异步与并发: 如果您的应用涉及大量并发的LLM调用,确保您的令牌计数器能够正确处理并发写入,例如使用原子操作或适当的锁机制(在JavaScript中可能需要考虑更高级的并发控制策略,或者将计数逻辑放在单线程事件循环中)。

总结

尽管LangChain.js目前没有像Python那样直接的get_openai_callback()方法来获取令牌消耗,但通过利用ChatOpenAI的callbacks属性和handleLLMEnd回调函数,开发者可以有效地追踪每次LLM调用的令牌使用情况。这种方法不仅有助于精确监控成本,还能为性能分析和资源优化提供宝贵的数据。在实施时,请务必关注模型兼容性、成本计算逻辑以及在复杂应用场景下的计数器管理。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1566

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

241

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

150

2025.10.17

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6607

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

842

2023.09.14

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

1092

2023.12.21

token什么意思
token什么意思

token是一种用于表示用户权限、记录交易信息、支付虚拟货币的数字货币。可以用来在特定的网络上进行交易,用来购买或出售特定的虚拟货币,也可以用来支付特定的服务费用。想了解更多token什么意思的相关内容可以访问本专题下面的文章。

2145

2024.03.01

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

93

2025.09.18

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号