📌 内容摘要

  • Claude 有多种省钱机制,但很多人不知道该用哪个——本文的目的是帮你在10秒内找到适合当前场景的策略。
  • 四大场景分类:实时对话、批量离线处理、长文档反复查询、高频简单任务——每种场景有不同的最优解。
  • 不只说”用什么”,还说”为什么这个场景不适合另一种策略”,帮你避免用错工具。
  • 文末附组合策略:同时满足多个场景条件时,怎么叠加使用省钱机制。

一、先用这张决策树定位你的场景

用户需要实时等待结果?
├── 否(离线/后台处理)
│   └── → 场景A:批量离线处理
│         优先策略:Batch API(5折)
│
└── 是(实时响应)
    │
    每次请求是否携带大量重复内容(如同一份文档/长System Prompt)?
    ├── 是
    │   └── → 场景B:长文档反复查询
    │         优先策略:Prompt Caching(输入省90%)
    │
    └── 否
        │
        任务是否简单(分类/提取/判断,输出很短)?
        ├── 是,且调用量大
        │   └── → 场景C:高频简单任务
        │         优先策略:Haiku 模型 + 小 max_tokens
        │
        └── 否(复杂对话/内容生成)
            └── → 场景D:实时对话/内容生成
                  优先策略:Sonnet + 对话历史裁剪

二、场景 A:批量离线处理

典型情况:每天批量跑数据标注、内容审核、摘要生成、报告处理——任务量大,但不需要实时返回结果,可以等几十分钟到几小时。

核心策略:Batch API,直接5折。

import anthropic
import json
import time

client = anthropic.Anthropic()

# ── 提交批量任务 ──────────────────────────────────

def submit_batch(items: list[dict], system: str = "") -> str:
    """
    提交批量任务,返回 batch_id
    items 格式:[{"id": "唯一ID", "text": "要处理的文本"}]
    """
    requests = []
    for item in items:
        messages = [{"role": "user", "content": item["text"]}]
        req = anthropic.types.MessageCreateParamsNonStreaming(
            model      = "claude-haiku-4-5-20251001",   # 批量任务优先用 Haiku 进一步省钱
            max_tokens = 64,
            messages   = messages,
        )
        if system:
            req["system"] = system
        requests.append(req)

    batch = client.messages.batches.create(requests=requests)
    print(f"✅ 已提交 {len(items)} 个任务,batch_id:{batch.id}")
    print(f"💰 预计费用:标准价格的 50%")
    return batch.id


# ── 轮询状态 ──────────────────────────────────────

def wait_for_batch(batch_id: str, poll_interval: int = 30) -> bool:
    """等待批量任务完成,返回是否成功"""
    print(f"等待任务完成(每 {poll_interval}s 检查一次)...")
    while True:
        batch = client.messages.batches.retrieve(batch_id)
        counts = batch.request_counts
        print(
            f"  进度:完成 {counts.succeeded + counts.errored}/"
            f"{counts.processing + counts.succeeded + counts.errored + counts.canceled} "
            f"(成功 {counts.succeeded},失败 {counts.errored})"
        )
        if batch.processing_status == "ended":
            return counts.errored == 0
        time.sleep(poll_interval)


# ── 获取结果 ──────────────────────────────────────

def get_batch_results(batch_id: str) -> dict[str, str]:
    """获取所有成功的结果,返回 {custom_id: 输出文本}"""
    results = {}
    for result in client.messages.batches.results(batch_id):
        if result.result.type == "succeeded":
            results[result.custom_id] = result.result.message.content[0].text
        else:
            results[result.custom_id] = f"[失败:{result.result.error.type}]"
    return results


# ── 完整流程示例 ──────────────────────────────────

items = [
    {"id": f"item_{i}", "text": f"判断情感(只输出:正面/负面/中性):{text}"}
    for i, text in enumerate([
        "这款产品超出预期,强烈推荐!",
        "质量太差了,完全不值这个价",
        "还行,就这样",
        "快递很快,东西不错",
        "假货,差评!",
    ])
]

batch_id = submit_batch(items)

# 实际项目:把 batch_id 存数据库,后台定时检查,不要阻塞主进程
# 演示用:直接等待
if wait_for_batch(batch_id, poll_interval=10):
    results = get_batch_results(batch_id)
    for item_id, output in results.items():
        print(f"{item_id}: {output}")

这个场景不要用的策略:

  • Prompt Caching——批量任务里每条输入都不同,缓存命中率为零,开了也没用
  • 流式输出——批量任务不需要实时展示,开流式反而增加复杂度

进一步省钱:Batch API 已经5折,再叠加”用 Haiku 代替 Sonnet”,综合成本可以降到标准 Sonnet 价格的 约16%(0.5 × Haiku价格/Sonnet价格 ≈ 0.5 × 0.33 = 16%)。

三、场景 B:长文档反复查询

典型情况:一份合同/手册/报告,用户会反复问不同的问题;或者 System Prompt 很长(几千 token),每次请求都要带上。

核心策略:Prompt Caching,重复内容只收 10% 的输入费用。

import anthropic

client = anthropic.Anthropic()

class CachedDocumentQA:
    """
    对同一份文档反复提问的问答系统
    文档内容只在第一次请求时全价计费,后续请求只收 10%
    """

    def __init__(self, document: str, model: str = "claude-sonnet-4-6"):
        self.document = document
        self.model    = model
        self.history  = []

    def ask(self, question: str) -> dict:
        self.history.append({"role": "user", "content": question})

        # 把文档放在 system 里并标记缓存
        response = client.messages.create(
            model      = self.model,
            max_tokens = 1024,
            system     = [
                {
                    "type": "text",
                    "text": f"你是文档分析助手。以下是参考文档:\n\n{self.document}",
                    "cache_control": {"type": "ephemeral"},  # 标记为可缓存
                }
            ],
            messages   = self.history,
        )

        answer = response.content[0].text
        self.history.append({"role": "assistant", "content": answer})

        # 统计缓存效果
        usage         = response.usage
        cache_created = getattr(usage, "cache_creation_input_tokens", 0)
        cache_hit     = getattr(usage, "cache_read_input_tokens", 0)
        normal_input  = usage.input_tokens

        if cache_created > 0:
            status = f"首次(写入缓存 {cache_created} tokens,下次省 90%)"
        elif cache_hit > 0:
            saved_pct = cache_hit / (cache_hit + normal_input) * 90
            status    = f"缓存命中 {cache_hit} tokens(节省约 {saved_pct:.0f}% 输入费用)"
        else:
            status = "未命中缓存"

        return {"answer": answer, "cache_status": status}


# 使用示例
doc = open("contract.txt").read()   # 假设这是一份几千 token 的合同
qa  = CachedDocumentQA(doc)

questions = [
    "合同的付款条款是什么?",
    "违约金是怎么计算的?",
    "合同有效期是多久?",
    "哪一方负责承担运费?",
]

for q in questions:
    result = qa.ask(q)
    print(f"Q:{q}")
    print(f"A:{result['answer'][:80]}...")
    print(f"缓存状态:{result['cache_status']}\n")

缓存命中的条件:

  • 缓存的内容要在请求的开头,且完全一致(一个字符不同就不命中)
  • 缓存有效期大约5分钟——超过5分钟不请求,缓存失效,下次重新写入
  • 缓存写入时费用是标准输入的 1.25 倍(首次稍贵),后续读取只收 0.1 倍

这个场景的成本计算示意:

文档:10000 tokens,对话 20 轮,每轮问题约 50 tokens

不用缓存:
  每轮输入 = 10000(文档)+ 历史 + 50(问题)≈ 10100 tokens
  20 轮总输入 ≈ 202000 tokens
  Sonnet 费用 ≈ $0.606

用缓存(5分钟内完成20轮):
  第1轮:写入缓存 10000 tokens × 1.25倍 + 100 tokens = $0.038
  第2-20轮:缓存命中 10000 tokens × 0.1倍 + 100 tokens × 正常价 ≈ $0.006/轮
  20 轮总费用 ≈ $0.038 + 19 × $0.006 ≈ $0.152

节省约 75%

四、场景 C:高频简单任务

典型情况:每天调用量很大(万次以上),但每次任务简单——情感判断、意图分类、关键词提取、是否违规检测。输入短,输出短,对质量要求不极致。

核心策略:Haiku 模型 + 精准控制 max_tokens。

import anthropic
from concurrent.futures import ThreadPoolExecutor

client = anthropic.Anthropic()

# 针对不同任务类型的最优配置
TASK_CONFIGS = {
    "sentiment": {
        "model":      "claude-haiku-4-5-20251001",
        "max_tokens": 8,      # 只需要输出"正面/负面/中性"
        "system":     "判断情感。只输出:正面、负面、或中性。",
    },
    "intent": {
        "model":      "claude-haiku-4-5-20251001",
        "max_tokens": 16,     # 意图类别名通常不超过10字
        "system":     "判断用户意图类别。只输出类别名,不要解释。",
    },
    "language": {
        "model":      "claude-haiku-4-5-20251001",
        "max_tokens": 8,      # 语言代码,如 zh/en/ja
        "system":     "识别文本语言。只输出 ISO 639-1 语言代码(如 zh、en、ja)。",
    },
    "toxic": {
        "model":      "claude-haiku-4-5-20251001",
        "max_tokens": 4,      # 是/否
        "system":     "判断内容是否包含有害信息。只输出:是 或 否。",
    },
}


def classify(text: str, task: str) -> str:
    """高频分类的最优配置调用"""
    config = TASK_CONFIGS[task]
    response = client.messages.create(
        model      = config["model"],
        max_tokens = config["max_tokens"],
        temperature= 0,         # 分类任务用零温度,结果稳定
        system     = config["system"],
        messages   = [{"role": "user", "content": text}],
    )
    return response.content[0].text.strip()


def batch_classify_concurrent(
    texts: list[str],
    task:  str,
    workers: int = 10,
) -> list[str]:
    """并发处理,提高吞吐量(注意不要超过速率限制)"""
    with ThreadPoolExecutor(max_workers=workers) as executor:
        results = list(executor.map(lambda t: classify(t, task), texts))
    return results


# 成本对比
def cost_comparison(daily_requests: int, avg_input_tokens: int):
    print(f"\n每日 {daily_requests:,} 次请求,平均输入 {avg_input_tokens} tokens")
    print(f"{'模型':<12} {'月费(美元)':>15} {'月费(人民币)':>15}")
    print("-" * 45)

    configs = [
        ("Haiku", 1.0, 5.0),
        ("Sonnet", 3.0, 15.0),
    ]
    for name, inp_price, out_price in configs:
        monthly = daily_requests * 30
        cost    = monthly * (avg_input_tokens * inp_price + 8 * out_price) / 1_000_000
        print(f"{name:<12} ${cost:>14.2f} ¥{cost*7.24:>14.1f}")


# 示例:评论情感分析,每天10万条
cost_comparison(100_000, avg_input_tokens=80)

这个场景不要用的策略:

  • Prompt Caching——每条输入都不同,没有可缓存的重复内容
  • Opus 或 Sonnet——高频简单任务不需要强模型,用 Haiku 已经够准确
  • 大 max_tokens——分类任务输出几个字就够,设1024是浪费

五、场景 D:实时对话和内容生成

典型情况:聊天机器人、写作助手、实时问答——用户等待回复,需要流式输出,对话历史在积累。

核心策略:Sonnet + 对话历史裁剪 + 精简 System Prompt。

import anthropic

client = anthropic.Anthropic()

class CostEfficientChatbot:
    """
    成本高效的聊天机器人
    核心省钱点:对话历史滑动窗口 + 精简 System Prompt
    """

    def __init__(
        self,
        system:       str,
        max_history:  int   = 10,   # 保留最近10轮对话
        model:        str   = "claude-sonnet-4-6",
        max_tokens:   int   = 1024,
    ):
        self.system      = system
        self.max_history = max_history
        self.model       = model
        self.max_tokens  = max_tokens
        self.history     = []
        self.total_cost  = 0.0

    def _trim_history(self):
        """滑动窗口:只保留最近 N 轮"""
        max_messages = self.max_history * 2   # 每轮 = user + assistant
        if len(self.history) > max_messages:
            self.history = self.history[-max_messages:]

    def _estimate_cost(self, input_tokens: int, output_tokens: int) -> float:
        """估算本次请求费用(Sonnet 价格)"""
        return (input_tokens * 3 + output_tokens * 15) / 1_000_000

    def chat(self, message: str) -> str:
        self.history.append({"role": "user", "content": message})
        self._trim_history()

        response = client.messages.create(
            model      = self.model,
            max_tokens = self.max_tokens,
            system     = self.system,
            messages   = self.history,
        )

        reply = response.content[0].text
        self.history.append({"role": "assistant", "content": reply})

        # 记录成本
        cost = self._estimate_cost(
            response.usage.input_tokens,
            response.usage.output_tokens,
        )
        self.total_cost += cost

        return reply

    def get_stats(self) -> dict:
        return {
            "history_turns":  len(self.history) // 2,
            "total_cost_usd": round(self.total_cost, 6),
        }


# 对话历史滑动窗口的省钱效果
def show_history_savings():
    """演示不裁剪 vs 裁剪历史的费用差异"""
    print("对话历史对成本的影响(每轮平均 200 tokens 输入 + 150 tokens 输出):")
    print(f"{'轮次':<6} {'不裁剪(累计输入)':>20} {'裁剪到10轮(输入)':>20}")
    print("-" * 50)

    for turn in [1, 5, 10, 20, 50]:
        no_trim  = turn * (200 + 150 * (turn - 1) / 2)   # 历史不断积累
        trimmed  = min(turn, 10) * 200 + 150 * min(turn - 1, 9) / 2   # 最多10轮
        print(f"{turn:<6} {no_trim:>20,.0f} tokens  {trimmed:>16,.0f} tokens")

show_history_savings()

System Prompt 精简的实际效果:

冗长版本(约 500 tokens):
"你是一个非常专业且经验丰富的客服助手,你的职责是帮助用户解决各种问题,
你需要保持礼貌、专业、友善的态度,始终以用户满意为目标……"

精简版本(约 20 tokens):
"你是专业客服助手。礼貌、准确,不确定时直说。"

每次请求节省 480 tokens × Sonnet 输入价格 $3/M = 每次省 $0.00144
每天 10000 次请求 × $0.00144 = $14.4 / 天 = $432 / 月

六、组合策略:多个场景条件同时满足时

实际项目往往不是单一场景,可以叠加使用多种策略:

组合场景 叠加策略 综合节省
批量处理 + 任务简单 Batch API(5折)× Haiku(比 Sonnet 便宜 3x) 约 83%
长文档 + 实时问答 Prompt Caching(文档省90%)+ 历史裁剪 约 70-80%
高频对话 + 路由分流 Haiku 判断意图路由,简单问题 Haiku 直答,复杂转 Sonnet 约 40-60%
批量处理 + 长固定 Prompt Batch API(5折)+ Prompt Caching(输入省90%) 约 90%+

组合策略代码示例:批量 + 长固定 Prompt

"""
场景:每天批量处理1000篇文章,
每篇文章都要对照同一份3000 token 的行业规范进行合规审查

策略叠加:
- Batch API:整体5折
- Prompt Caching:规范文档复用,输入省90%
"""

COMPLIANCE_STANDARD = """
[一份3000 token的行业合规规范文档]
...[内容省略]...
"""

def build_compliance_batch_request(article: str, article_id: str):
    """构建带缓存标记的批量审查请求"""
    return anthropic.types.MessageCreateParamsNonStreaming(
        model      = "claude-haiku-4-5-20251001",
        max_tokens = 128,
        system     = [
            {
                "type": "text",
                "text": f"对照以下合规规范审查文章。规范:\n\n{COMPLIANCE_STANDARD}",
                "cache_control": {"type": "ephemeral"},   # 规范文档缓存
            }
        ],
        messages   = [{"role": "user", "content": f"审查以下文章是否合规(通过/不通过/需人工审查):\n\n{article}"}],
    )

# 注意:Batch API + Prompt Caching 可以同时使用
# Batch API 负责批量提交(5折)
# Prompt Caching 负责复用固定的规范文档(输入省90%)
# 两个机制在 API 层面完全兼容

七、不适合省钱的情况

不是所有任务都应该省钱——有些情况强行优化反而有代价:

  • 用 Haiku 处理复杂推理任务:准确率下降的代价远超省下的费用,下游需要更多人工干预
  • 批量任务强行用 Batch API:Batch API 有延迟(最长24小时),如果业务有时效性要求,用了反而误事
  • 对话历史裁剪过激:把窗口设得太短,Claude 记不住前面的上下文,用户体验变差,客诉增加
  • Prompt 精简过度:压缩到 System Prompt 没有足够约束,输出质量下滑,需要更多人工审核

省钱的正确姿势是:先确认质量达标,再在不影响质量的前提下优化成本。质量和成本通常是可以兼顾的,但质量优先。

总结:一张速查表

你的情况 第一优先策略 可叠加
不需要实时结果 Batch API(固定5折) + Haiku 模型
同一文档反复查询 Prompt Caching(省90%输入) + 历史裁剪
任务简单、调用量大 Haiku 模型 + 小 max_tokens + Batch API
多轮对话积累 滑动窗口裁剪历史 + 精简 System Prompt
复杂任务混合简单任务 Haiku 路由分流 + 各场景独立优化