有效部署 LangChain 应用,不仅要管理性能,还要管理运营支出。大型语言模型虽然功能强大,但会消耗计算资源,其使用通常直接转化为金钱成本,主要是通过按令牌定价的 API 调用。忽视成本管理可能导致不可持续的运营费用,尤其是在应用扩展时。这里提供了理解、追踪和控制 LangChain 应用相关成本的策略,主要关注令牌使用量,这是大型语言模型开销的主要因素。了解令牌经济大多数商业大型语言模型提供商(如 OpenAI、Anthropic、Google)采用基于处理“令牌”数量的即用即付模式。一个令牌大致对应一个单词或单词的一部分。了解这些成本如何产生非常重要:输入与输出定价: 许多模型对于发送给模型(输入/提示令牌)的令牌和从模型接收(输出/完成令牌)的令牌有不同的价格点。通常,输出令牌更昂贵。模型层级: 同一提供商系列中,不同模型的定价差异很大。例如,OpenAI 的 GPT-4 模型每个令牌的价格远高于其 GPT-3.5 Turbo 模型。这反映了能力、规模和计算需求上的差异。上下文的作用: 你发送的提示,包括 RAG 系统中检索到的任何上下文或对话历史,都会计入输入令牌数量。冗长、详细的提示或大量的上下文会直接增加成本。计算方法: 单次大型语言模型调用的基本成本公式通常为: $$ \text{成本} = (\text{输入令牌} \times \text{输入价格}) + (\text{输出令牌} \times \text{输出价格}) $$ 其中 $\text{Price}{\text{input}}$ 和 $\text{Price}{\text{output}}$ 分别是所用特定模型的输入和输出的每令牌成本。了解这种定价结构是实现有效成本管理的第一步。你需要清楚地知道你的应用消耗了多少令牌以及在何处消耗。在 LangChain 中追踪令牌使用量LangChain 提供了便捷的方式来追踪令牌使用量,特别是对于通过 OpenAI 等标准 API 进行接口的模型。主要的机制涉及使用回调(Callbacks)。get_openai_callback 上下文管理器是一种简单的方法,可以追踪执行 OpenAI 调用的代码块的使用情况:from langchain_openai import ChatOpenAI from langchain.callbacks import get_openai_callback from langchain.schema import HumanMessage # 假设 OPENAI_API_KEY 已在环境变量中设置 llm = ChatOpenAI(model_name="gpt-3.5-turbo") messages = [HumanMessage(content="Explain the concept of tokenization in LLMs in about 50 words.")] # 使用回调上下文管理器 with get_openai_callback() as cb: response = llm.invoke(messages) print(response.content) print("\n--- Usage Stats ---") print(f"Total Tokens: {cb.total_tokens}") print(f"Prompt Tokens: {cb.prompt_tokens}") print(f"Completion Tokens: {cb.completion_tokens}") print(f"Total Cost (USD): ${cb.total_cost:.6f}") 当你运行这段代码时,get_openai_callback 上下文管理器(cb)会捕获在 with 块内进行的大型语言模型调用的令牌计数和预估成本。它提供了诸如 total_tokens、prompt_tokens、completion_tokens 和 total_cost 等属性。对于涉及链或代理的更复杂场景,或者在处理异步操作时,你可能需要更精细的追踪方法:自定义回调处理器: 你可以实现继承自 BaseCallbackHandler 的自定义回调处理器,以在多个步骤或异步任务中汇总令牌计数。这些处理器可以将数据记录到数据库、监控系统或自定义仪表板。链/代理的详细输出: 使用 verbose=True 运行链或代理通常会打印单个步骤的令牌使用信息,这在开发期间可能有用,但对于生产环境的日志记录则不太实用。利用 LangSmith 进行全面的成本监控虽然内置回调很有用,但 LangSmith 提供了一个更加集成和强大的生产监控解决方案,其中包括成本追踪。当你配置 LangChain 应用使用 LangSmith 时(如第 5 章所述),它会自动捕获应用执行的详细轨迹,包括:令牌计数: 对于轨迹中的每次大型语言模型调用,LangSmith 都会记录提示令牌、完成令牌和总令牌。预估成本: 根据所用模型和令牌计数,LangSmith 会自动计算每次大型语言模型交互的预估成本。聚合功能: LangSmith 用户界面允许你查看跨不同轨迹、时间段或项目的聚合令牌使用量和成本。你可以轻松识别哪些链、代理或特定的大型语言模型调用对你的总成本贡献最大。元数据标签: 你可以为 LangChain 调用或 LangSmith 轨迹添加自定义标签(例如,用户 ID、会话 ID、功能名称)。这实现了细粒度的成本归因,让你能够分析多租户应用中按用户、按功能或按租户的成本。使用 LangSmith 将成本追踪从手动日志记录或简单回调转变为一个持久、可搜索和可聚合的系统,显著提升了生产环境中的可见性。digraph G { bgcolor="transparent"; node [shape=box, style=rounded, fontname="Arial", fontsize=10, margin=0.2, color="#adb5bd"]; edge [fontname="Arial", fontsize=9, color="#495057"]; UserInput [label="用户输入"]; RAGChain [label="RAG 链"]; Retriever [label="检索器"]; LLM [label="大型语言模型调用\n(追踪令牌/成本)", color="#fa5252", style="rounded,filled", fillcolor="#ffc9c9"]; Output [label="最终输出"]; LangSmith [label="LangSmith\n(记录轨迹、令牌、成本)", shape=cylinder, color="#4263eb", style="filled", fillcolor="#bac8ff"]; UserInput -> RAGChain; RAGChain -> Retriever [label="查询"]; Retriever -> RAGChain [label="上下文文档"]; RAGChain -> LLM [label="提示 + 上下文"]; LLM -> RAGChain [label="大型语言模型响应"]; RAGChain -> Output; LLM -> LangSmith [style=dashed, arrowhead=open]; {rank=same; Retriever; LLM} }一个简化的流程图,展示了 RAG 应用中令牌使用量和成本通常在何处被追踪(在大型语言模型调用处)和记录(例如,到 LangSmith)。成本削减策略一旦你对令牌使用量和成本有了清晰的了解,就可以实施策略来削减支出:模型选择策略: 这通常是影响最大的一个因素。评估是否可以使用成本较低的模型(例如 GPT-3.5-Turbo、Claude Haiku)来充分完成某些任务,而不是默认使用功能最强大(也最昂贵)的选项(例如 GPT-4、Claude Opus)。如果你有特定、重复的任务,可以考虑微调更小型的开源模型,尽管这会涉及前期训练成本。提示优化: 简洁性很重要。优化你的提示,使其尽可能简洁,同时仍能达到预期输出。删除冗余的指令或示例。分析少样本示例是否总是必需的。上下文窗口管理: 在 RAG 或对话系统中,发送过多的上下文会显著增加输入令牌计数。可使用以下方法:总结归纳: 在将对话历史或长文档包含在提示中之前进行总结(第 3 章)。选择性检索: 提高检索准确性(第 4 章),以便只发送最相关的片段,而不是大量可能不相关的文本。滑动窗口: 对于长时间对话,只包含最近的回合。大型语言模型响应缓存: 如果你的应用频繁收到相同的请求,缓存大型语言模型响应可以带来显著的成本节约和延迟改善。LangChain 提供了多种缓存实现(InMemoryCache、SQLAlchemyCache、RedisCache 等)。如果底层数据或预期响应可能发生变化,请注意缓存失效问题。import langchain from langchain_openai import OpenAI from langchain.cache import InMemoryCache # 全局启用缓存 langchain.llm_cache = InMemoryCache() llm = OpenAI(model_name="gpt-3.5-turbo-instruct") # 第一次调用(将调用 API 并缓存结果) print("First call:") result1 = llm.invoke("Why is the sky blue?") # print(result1) # 为简洁省略输出 # 第二次调用,使用完全相同的提示(将从缓存返回) print("\nSecond call (cached):") result2 = llm.invoke("Why is the sky blue?") # print(result2) # 为简洁省略输出 # 注意:get_openai_callback 不会显示缓存调用的成本/令牌控制输出长度: 在你的大型语言模型调用中使用 max_tokens 参数来限制生成响应的长度。当你只需要一个简短的答案、摘要或分类时,这非常有用,可以防止模型生成过长(且昂贵)的文本。请求批量处理: 一些大型语言模型 API 支持批量处理,允许你在单个请求中发送多个独立的提示。虽然这通常不会改变每令牌成本,但可以减少网络开销并可能提高整体吞吐量,从而间接影响基础设施成本。请查阅你的提供商文档,了解批量处理功能和定价。{ "layout": { "title": { "text": "月度成本:模型比较" }, "xaxis": { "title": { "text": "模型" } }, "yaxis": { "title": { "text": "预估月度成本 (美元)" }, "range": [0, 550] }, "legend": { "traceorder": "reversed" }, "autosize": true, "height": 350, "template": "plotly_white", "margin": { "l": 50, "r": 20, "t": 50, "b": 50 } }, "data": [ { "type": "bar", "x": ["GPT-3.5-Turbo", "GPT-4", "GPT-4 (Cached)"], "y": [100, 500, 200], "marker": { "color": ["#96f2d7", "#ffc9c9", "#bac8ff"], "line": { "color": "#495057", "width": 1 } }, "name": "成本" } ] }示例性地比较了使用不同模型或技术处理相同工作负载的月度成本。缓存显著降低了与未缓存的 GPT-4 使用相比的成本,如果某些请求需要 GPT-4 的质量,这可能比一直使用更便宜的 GPT-3.5 模型更可行。成本归因与预算在生产环境中,尤其是在多功能或多租户应用中,仅仅知道总成本是不够的。你需要将成本归因于具体的活动:标签化: 使用 LangSmith 的标签功能或自定义日志记录,将 API 调用与用户 ID、会话 ID、租户 ID 或功能标志关联起来。数据分析: 定期分析按这些标签细分的成本数据(例如,在 LangSmith 或你自己的监控仪表板中)。这有助于确定哪些功能或用户产生的成本最高。预算设置: 为大型语言模型的总使用量或特定功能/团队设定预算。设置警报(可能通过 LangSmith 集成或自定义监控)在支出接近或超出预算阈值时通知你。积极的成本管理需要持续的监控、分析和优化。通过细致地追踪令牌使用量,有效使用 LangSmith 等工具,并应用成本节约策略,你可以确保 LangChain 应用在扩展时仍保持经济上的可行性。这种积极主动的方法是负责任地运营生产级大型语言模型系统不可或缺的一部分。