教程 / 后端集成 / 使用 Claude API 构建应用
📝 文字 ● 中级 更新于 2026-05-19

使用 Claude API 构建应用 — 提示词缓存、工具调用与模型迁移

没有启用提示词缓存的 Claude API 集成,等于在重复为已付过的 Token 买单。仅凭缓存一项,通常就能将费用削减一半。本教程带你走完 Anthropic SDK 的标准调用范式,以及真正影响账单的优化手段——并说明新模型发布时,哪些地方需要改、哪些不用动。

为什么"能跑就行"是最贵的默认选项

0

文档里最短的 Anthropic SDK 示例确实能运行——但它默认带着三个软性缺陷,在任何有真实流量的场景下都会烧钱:

  • 没有提示词缓存。每次请求都要重新计费完整的系统提示、完整的工具定义,以及上传的所有上下文。缓存后的 Token 费用约为基础输入价格的 10%。如果你的聊天机器人有 4 KB 的系统提示、每天 100 个用户,跳过缓存等于每天都在白白花钱。
  • 用字符串解析来处理工具调用。手写"如果模型返回 SEARCH(...) 就执行搜索"这类逻辑,是一条充满痛苦的路——脆弱、没有 Schema 校验、不支持并行工具调用。SDK 提供了完善的 tools 结构,直接用它就好。
  • 模型字符串硬编码到处都是。下一个 Sonnet 或 Opus 发布时,你希望只改一行,而不是改十二行。把它集中管理。

LingCode 理解 Anthropic SDK 的调用范式,生成的集成代码默认包含缓存、工具调用和模型常量——让它来构建功能,你第一次拿到的就是优化后的版本。

你需要准备什么

1
  • LingCode下载安装包
  • Anthropic API 密钥 — 在 console.anthropic.com 获取。将其写入 .env 文件,变量名为 ANTHROPIC_API_KEY
  • Node 或 Python 项目 — 下方示例使用 TypeScript(@anthropic-ai/sdk),因为它覆盖了最完整的 API 形态;Python 版 anthropic SDK 与之方法一一对应。

最简标准调用

2

让 LingCode 帮你搭建 SDK 的初始结构。它生成的代码形态如下:

// src/claude.ts
import Anthropic from "@anthropic-ai/sdk";

const MODEL = "claude-sonnet-4-7-20260101"; // one place to bump
const client = new Anthropic(); // reads ANTHROPIC_API_KEY from env

export async function ask(userText: string) {
  const res = await client.messages.create({
    model: MODEL,
    max_tokens: 1024,
    messages: [{ role: "user", content: userText }],
  });
  return res.content[0].type === "text" ? res.content[0].text : "";
}

有三点值得注意:MODEL 是一个常量——所有调用都通过它路由。max_tokens 是显式指定的——SDK 要求必须提供。响应体是一个内容块数组,而不是字符串;模型可能返回多个块(文本、工具调用、思考过程),所以要始终检查类型。

Python 的写法完全一样。 from anthropic import Anthropic; client = Anthropic(); client.messages.create(...)。选你后端使用的语言即可,API 接口是一致的。

提示词缓存 — 不可跳过的优化

3

如果每次请求的系统提示都相同——通常都是——就把它标记为可缓存,第一次调用之后只需支付基础价格的 10%。五分钟的改动,有时能省下一半账单。

const SYSTEM_PROMPT = `You are a support agent for Acme Widgets.
Your knowledge base:

${KNOWLEDGE_BASE_TEXT}

Always cite the section number when answering.`;

const res = await client.messages.create({
  model: MODEL,
  max_tokens: 1024,
  system: [
    {
      type: "text",
      text: SYSTEM_PROMPT,
      cache_control: { type: "ephemeral" },
    },
  ],
  messages: [{ role: "user", content: userText }],
});

有两条规则需要牢记:

  • 缓存稳定的前缀部分。系统提示、工具定义、用户正在查询的大型文档——任何在对话轮次之间不会变化的内容都适合缓存。缓存键是字面的前缀字节,因此哪怕改动一个字符都会使缓存失效。
  • 有最小 Token 数限制。被缓存的内容块有 Token 数量下限(撰写本文时,Sonnet 为 1024,Haiku 为 2048)。太短的系统提示不会被缓存——SDK 也不会报错,只是悄悄按全价计费。请通过响应中的 res.usage.cache_creation_input_tokenscache_read_input_tokens 来确认缓存是否真正命中。
注意缓存的 TTL。临时缓存条目在最后一次命中后约 5 分钟过期。如果你的流量是突发型的(发一个请求,然后 10 分钟没有流量),每次突发都要重新付创建成本。对于稳定的高流量,临时缓存是净收益;对于不规律的流量,需要权衡。

工具调用 — 正确的姿势

4

工具调用是一个三步协议:你声明工具,模型返回 tool_use 块,你回复 tool_result。SDK 提供了类型化的结构;不要把它退化成字符串解析。

const tools = [
  {
    name: "get_weather",
    description: "Get current weather for a city.",
    input_schema: {
      type: "object",
      properties: {
        city: { type: "string", description: "City name, e.g. 'Paris'." },
      },
      required: ["city"],
    },
  },
];

let messages = [{ role: "user", content: "What's the weather in Tokyo?" }];

while (true) {
  const res = await client.messages.create({
    model: MODEL,
    max_tokens: 1024,
    tools,
    messages,
  });

  if (res.stop_reason !== "tool_use") {
    // Plain answer — done.
    return res.content;
  }

  // The model wants a tool. Run it, reply, loop.
  const toolUse = res.content.find((b) => b.type === "tool_use");
  const result = await runTool(toolUse.name, toolUse.input);

  messages.push({ role: "assistant", content: res.content });
  messages.push({
    role: "user",
    content: [
      {
        type: "tool_result",
        tool_use_id: toolUse.id,
        content: JSON.stringify(result),
      },
    ],
  });
}

stop_reason 不是 tool_use 时(通常是 end_turn),循环结束。模型可能在一次响应中返回多个 tool_use 块(即并行工具调用);把它们全部执行,然后在一条用户消息中返回所有 tool_result

也要缓存工具数组。工具定义在请求间是稳定的——在列表最后一个工具上添加 cache_control: { type: "ephemeral" },即可将整个工具块标记为可缓存。工具数组越大,效果和缓存大型系统提示一样显著。

流式输出 — 让聊天界面不再让用户等

5

同样的调用,改为流式:

const stream = client.messages.stream({
  model: MODEL,
  max_tokens: 1024,
  messages: [{ role: "user", content: userText }],
});

for await (const event of stream) {
  if (event.type === "content_block_delta" &&
      event.delta.type === "text_delta") {
    process.stdout.write(event.delta.text);
  }
}

const final = await stream.finalMessage();
console.log("usage:", final.usage);

流式事件包括 message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stop。大多数 UI 场景只需要渲染 text_delta 增量;其余的是内务事件。finalMessage() 会返回完整响应——用量统计和停止原因都在里面。

其他值得了解的接口

6

LingCode 可以帮你接入以下任何一项,但它们不是随意的选择——每个都有特定的适用场景:

  • Batch API。一次提交最多 10 万个请求,24 小时内返回结果,价格比同步调用便宜 50%。适合夜间批量数据处理;不适合聊天场景。
  • Files API。上传一次 PDF 或文档,通过 ID 在多次请求中复用。当同一份文件被反复查询时,配合提示词缓存效果更佳。
  • 引用(Citations)。将文档作为内容块传入,并设置 citations: { enabled: true },模型会返回指向源文本片段的引用对象。这是真实的溯源,不是模型凭感觉给出的答案。
  • 扩展思考(Extended thinking)。在复杂问题上设置 thinking: { type: "enabled", budget_tokens: 5000 }。模型会生成一个 thinking 内容块(在工具调用间保持,不会重新推理)。代价是这些思考 Token 会计费。适合数学、代码、多步骤规划;对"总结这段话"这类任务则是大材小用。
  • 记忆(Memory)。新的 memory 工具让模型能在多个会话间写入持久笔记。适合长期运行的智能体;在依赖它之前,先确认该模型的训练数据中确实包含此工具(查看模型说明页)。

模型版本迁移

7

新的 Sonnet 或 Opus 发布时,迁移通常只需改一行——但回归检测是你的责任。API 在这些版本间是稳定的;模型的行为却不一定。

// Before
const MODEL = "claude-sonnet-4-6-20251022";

// After
const MODEL = "claude-sonnet-4-7-20260101";

替换后需要检查以下几点:

  • 运行现有的评估套件。如果你还没有,现在正是补上的时机——选 20 个有代表性的输入,对比两个模型版本的输出差异。
  • 重新验证提示词缓存。新模型 = 新缓存。第一次请求必然是缓存未命中,这是正常的。验证后续请求是否命中缓存(cache_read_input_tokens > 0)。
  • 重新验证工具调用结构。较新的模型有时偏好不同的工具参数结构。如果工具调用出现了回退,修复方法通常是收紧工具描述,而不是回滚模型版本。
  • 重新检查 max_tokens。较新的模型可能支持更大的输出窗口;如果你的提示词曾经被截断,考虑调高 max_tokens

废弃模型的迁移流程相同——Anthropic 会公布下线日期,在此之前更新常量即可。当你问 LingCode "当前 Sonnet 模型字符串是什么"时,它会读取模型废弃页面,并生成带回归测试的迁移代码。

不要在生产环境中使用 claude-3-5-sonnet-latest 这类别名。它们会在你不知情的情况下漂移。请固定到带日期的快照版本(如 claude-sonnet-4-7-20260101),并有计划地进行迁移。

费用监控 — 追踪真正重要的指标

8

每次 Anthropic 响应都携带用量统计。记录它们:

console.log({
  input: res.usage.input_tokens,
  output: res.usage.output_tokens,
  cache_create: res.usage.cache_creation_input_tokens,
  cache_read: res.usage.cache_read_input_tokens,
});

有两个数字值得重点关注:cache_read_input_tokens / (cache_read + input + cache_create) 是你的缓存命中率——对于聊天机器人来说,超过 50% 意味着缓存正在发挥作用。output_tokens / input_tokens 是你的冗余比——如果它在数周内持续上升,说明你的提示词在悄悄引导模型输出更长的回答,账单也在跟着涨。

在 LingCode 中使用这套工作流

9

将整套工作流封装成一个 Skill,这样每次让 LingCode 接入 Claude 时,它都能自动选择正确的 API 结构、缓存策略和模型常量:

---
name: claude-api
description: Build, debug, and optimize Claude API / Anthropic SDK apps in TypeScript or Python. Apps built with this skill should include prompt caching. Also handles migrating between Claude model versions (Sonnet/Opus/Haiku 4.5 → 4.6 → 4.7, retired-model replacements). Triggers: anthropic SDK import, @anthropic-ai/sdk usage, prompt caching questions, tool use loops, streaming, batch API, files API, citations, memory, thinking. Actions: build Claude app, add prompt caching, migrate model version, fix Anthropic API error, optimize tokens, wire tool use. Skip if: code imports openai or other-provider SDK.
---

When wiring or modifying Claude API code:

1. Use @anthropic-ai/sdk (TS) or anthropic (Python). Same shape.
2. Centralize the model string in one constant — never inline.
   Pin to dated snapshots, not -latest aliases.
3. Mark stable prefixes cacheable with
   cache_control: { type: "ephemeral" }: system prompt, tools
   array, large reused documents. Verify cache hits via
   res.usage.cache_read_input_tokens.
4. Use the SDK tool-use shape (tools: [...], tool_use block,
   tool_result reply). Never string-parse tool calls.
5. Handle parallel tool calls — a single response may contain
   multiple tool_use blocks; run all, reply with all tool_results
   in one user message.
6. For chat UIs, stream content_block_delta events. Use
   finalMessage() for the assembled response.
7. Log usage stats on every call. Watch cache hit rate and
   output/input ratio over time.
8. On model migrations: change the constant, re-run the eval
   suite, verify cache still hits, check tool-call shape didn't
   regress.

Prefer Batch API for offline enrichment (50% cheaper, 24h SLA).
Prefer Files API + caching for repeated queries against the same
document. Use extended thinking only when the problem warrants it
(math, code, multi-step planning).

保存为 ~/.lingcode/skills/claude-api/SKILL.md — 具体路径和 Skill 的发现机制,请参阅 安装 Skill

获取 LingCode →

下一步