Claude API 完整实战

前言

💡 痛点:想用 Claude API 但不知道如何开始?Messages API 不会用?工具调用(Tool Use)不理解?成本和限制不清楚?

🎯 解决方案 :掌握 Claude API 实战 --- 从基础调用、到高级特性、再到生产级最佳实践。

Claude API 能力全景:
#mermaid-svg-BWMB0R7kkfdEsUn2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BWMB0R7kkfdEsUn2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BWMB0R7kkfdEsUn2 .error-icon{fill:#552222;}#mermaid-svg-BWMB0R7kkfdEsUn2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BWMB0R7kkfdEsUn2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BWMB0R7kkfdEsUn2 .marker.cross{stroke:#333333;}#mermaid-svg-BWMB0R7kkfdEsUn2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BWMB0R7kkfdEsUn2 p{margin:0;}#mermaid-svg-BWMB0R7kkfdEsUn2 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BWMB0R7kkfdEsUn2 .cluster-label text{fill:#333;}#mermaid-svg-BWMB0R7kkfdEsUn2 .cluster-label span{color:#333;}#mermaid-svg-BWMB0R7kkfdEsUn2 .cluster-label span p{background-color:transparent;}#mermaid-svg-BWMB0R7kkfdEsUn2 .label text,#mermaid-svg-BWMB0R7kkfdEsUn2 span{fill:#333;color:#333;}#mermaid-svg-BWMB0R7kkfdEsUn2 .node rect,#mermaid-svg-BWMB0R7kkfdEsUn2 .node circle,#mermaid-svg-BWMB0R7kkfdEsUn2 .node ellipse,#mermaid-svg-BWMB0R7kkfdEsUn2 .node polygon,#mermaid-svg-BWMB0R7kkfdEsUn2 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BWMB0R7kkfdEsUn2 .rough-node .label text,#mermaid-svg-BWMB0R7kkfdEsUn2 .node .label text,#mermaid-svg-BWMB0R7kkfdEsUn2 .image-shape .label,#mermaid-svg-BWMB0R7kkfdEsUn2 .icon-shape .label{text-anchor:middle;}#mermaid-svg-BWMB0R7kkfdEsUn2 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BWMB0R7kkfdEsUn2 .rough-node .label,#mermaid-svg-BWMB0R7kkfdEsUn2 .node .label,#mermaid-svg-BWMB0R7kkfdEsUn2 .image-shape .label,#mermaid-svg-BWMB0R7kkfdEsUn2 .icon-shape .label{text-align:center;}#mermaid-svg-BWMB0R7kkfdEsUn2 .node.clickable{cursor:pointer;}#mermaid-svg-BWMB0R7kkfdEsUn2 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BWMB0R7kkfdEsUn2 .arrowheadPath{fill:#333333;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BWMB0R7kkfdEsUn2 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BWMB0R7kkfdEsUn2 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BWMB0R7kkfdEsUn2 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BWMB0R7kkfdEsUn2 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BWMB0R7kkfdEsUn2 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BWMB0R7kkfdEsUn2 .cluster text{fill:#333;}#mermaid-svg-BWMB0R7kkfdEsUn2 .cluster span{color:#333;}#mermaid-svg-BWMB0R7kkfdEsUn2 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BWMB0R7kkfdEsUn2 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BWMB0R7kkfdEsUn2 rect.text{fill:none;stroke-width:0;}#mermaid-svg-BWMB0R7kkfdEsUn2 .icon-shape,#mermaid-svg-BWMB0R7kkfdEsUn2 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BWMB0R7kkfdEsUn2 .icon-shape p,#mermaid-svg-BWMB0R7kkfdEsUn2 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BWMB0R7kkfdEsUn2 .icon-shape .label rect,#mermaid-svg-BWMB0R7kkfdEsUn2 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BWMB0R7kkfdEsUn2 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BWMB0R7kkfdEsUn2 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BWMB0R7kkfdEsUn2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Claude API
文本生成
多模态 Vision
工具调用 Tool Use
批量处理
Messages API
流式响应
系统提示
图片理解
文档分析
工具定义
并行工具调用
工具结果反馈
Batch API
异步处理

Claude 模型版本:

模型 发布时间 上下文窗口 特点
Claude 3 Haiku 2024.3 200K 最快、最便宜
Claude 3 Sonnet 2024.3 200K 平衡性能与成本
Claude 3 Opus 2024.3 200K 最强推理能力
Claude 3.5 Sonnet 2024.6 200K Sonnet 升级版
Claude 3.5 Haiku 2024.10 200K Haiku 升级版

一、快速开始

1.1 安装与配置

bash 复制代码
# ===== 安装 Anthropic SDK =====

# Python
pip install anthropic>=0.39.0

# Node.js
npm install @anthropic-ai/sdk

# Go
go get github.com/anthropics/anthropic-go

# 环境变量配置
export ANTHROPIC_API_KEY="sk-ant-..."
export ANTHROPIC_BASE_URL="https://api.anthropic.com"  # 可选

# Windows PowerShell
$env:ANTHROPIC_API_KEY = "sk-ant-..."
python 复制代码
# ===== 基础配置 =====

import os
from anthropic import Anthropic

# 初始化客户端
client = Anthropic(
    api_key=os.getenv("ANTHROPIC_API_KEY"),
    # base_url="https://api.anthropic.com",  # 默认
    # timeout=60.0,  # 超时时间
    # max_retries=2,  # 重试次数
)

# 简单调用
response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "你好!"}
    ]
)

print(response.content[0].text)

1.2 模型选择

python 复制代码
# ===== 模型选择指南 =====

models = {
    "claude-3-5-sonnet-20241022": {
        "description": "最新 Sonnet,性能最强",
        "context_window": 200000,
        "max_output": 8192,
        "price_input": 3.00,    # $/1M tokens
        "price_output": 15.00,
        "best_for": ["复杂推理", "代码生成", "分析任务"]
    },
    "claude-3-5-haiku-20241022": {
        "description": "最新 Haiku,速度最快",
        "context_window": 200000,
        "max_output": 8192,
        "price_input": 1.00,
        "price_output": 5.00,
        "best_for": ["快速响应", "简单任务", "大规模应用"]
    },
    "claude-3-opus-20240229": {
        "description": "最强推理能力",
        "context_window": 200000,
        "max_output": 4096,
        "price_input": 15.00,
        "price_output": 75.00,
        "best_for": ["复杂任务", "深度推理", "高质量输出"]
    },
    "claude-3-sonnet-20240229": {
        "description": "平衡性能与成本",
        "context_window": 200000,
        "max_output": 4096,
        "price_input": 3.00,
        "price_output": 15.00,
        "best_for": ["通用任务", "成本平衡"]
    },
    "claude-3-haiku-20240307": {
        "description": "最便宜,速度最快",
        "context_window": 200000,
        "max_output": 4096,
        "price_input": 0.25,
        "price_output": 1.25,
        "best_for": ["简单任务", "成本敏感"]
    }
}

# 选择建议
def select_model(task_complexity, need_speed, budget_sensitive):
    if task_complexity == "high":
        return "claude-3-opus-20240229"
    if need_speed and budget_sensitive:
        return "claude-3-5-haiku-20241022"
    if not budget_sensitive:
        return "claude-3-5-sonnet-20241022"
    return "claude-3-haiku-20240307"

1.3 基础对话

python 复制代码
# ===== 基础对话示例 =====

from anthropic import Anthropic
import os

client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

def simple_chat():
    """简单对话"""
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        system="你是一个有帮助的助手。",  # 系统提示
        messages=[
            {"role": "user", "content": "写一个快速排序算法"}
        ],
        temperature=0.7,  # 0-1,越高越随机
    )
    
    return response.content[0].text

def multi_turn_chat():
    """多轮对话"""
    messages = []
    
    while True:
        user_input = input("你: ")
        if user_input.lower() in ['exit', 'quit']:
            break
        
        messages.append({"role": "user", "content": user_input})
        
        response = client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1024,
            messages=messages,
            temperature=0.7
        )
        
        assistant_reply = response.content[0].text
        messages.append({"role": "assistant", "content": assistant_reply})
        
        print(f"AI: {assistant_reply}")

def stream_chat():
    """流式响应"""
    with client.messages.stream(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=[
            {"role": "user", "content": "讲一个长故事"}
        ]
    ) as stream:
        print("AI: ", end="")
        for text in stream.text_stream:
            print(text, end="", flush=True)
        print()  # 换行

二、Messages API 详解

2.1 消息结构

python 复制代码
# ===== Messages API 消息结构 =====

# 单条消息
response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    system="你是一个专业的 Python 开发者。",  # 系统提示(可选)
    messages=[
        {
            "role": "user",
            "content": "写一个快速排序算法"
        }
    ]
)

# 多轮对话
messages = [
    {"role": "user", "content": "什么是递归?"},
    {"role": "assistant", "content": "递归是..."},
    {"role": "user", "content": "能给个例子吗?"}
]

response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    messages=messages
)

# 系统提示可以是一个字符串,也可以是数组
response = client.messages.create(
    model="claude-3-5-sonnet-20241022",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "你是一个有帮助的助手。用中文回答。"
        }
    ],
    messages=[
        {"role": "user", "content": "你好!"}
    ]
)

2.2 内容类型(多模态)

python 复制代码
# ===== 多模态内容 =====

import base64
from anthropic import Anthropic

client = Anthropic()

def encode_image(image_path: str) -> str:
    """将图片编码为 base64"""
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')

# 图片 + 文本
def vision_example():
    base64_image = encode_image("image.jpg")
    
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "mime_type": "image/jpeg",
                            "data": base64_image
                        }
                    },
                    {
                        "type": "text",
                        "text": "描述这张图片"
                    }
                ]
            }
        ]
    )
    
    return response.content[0].text

# 多个图片
def multiple_images():
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": "比较这两张图片"},
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "mime_type": "image/jpeg",
                            "data": encode_image("image1.jpg")
                        }
                    },
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "mime_type": "image/jpeg",
                            "data": encode_image("image2.jpg")
                        }
                    }
                ]
            }
        ]
    )
    
    return response.content[0].text

# PDF 文档(需要先转为图片或文本)
def pdf_example():
    # Claude 不支持直接读取 PDF
    # 需要先将 PDF 转为图片,或使用其他工具提取文本
    pass

2.3 流式响应

python 复制代码
# ===== 流式响应 =====

from anthropic import Anthropic

client = Anthropic()

# 方式 1:使用 stream() 上下文管理器(推荐)
def stream_example():
    with client.messages.stream(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=[
            {"role": "user", "content": "讲一个长故事"}
        ]
    ) as stream:
        print("AI: ", end="")
        for text in stream.text_stream:
            print(text, end="", flush=True)
        print()

# 方式 2:使用 stream=True(手动处理)
def stream_manual():
    with client.messages.stream(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=[
            {"role": "user", "content": "讲一个长故事"}
        ]
    ) as stream:
        for event in stream:
            if event.type == "content_block_delta":
                if event.delta.type == "text_delta":
                    print(event.delta.text, end="", flush=True)
        print()

# 异步流式
import asyncio
from anthropic import AsyncAnthropic

async def async_stream():
    client = AsyncAnthropic()
    
    with client.messages.stream(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=[
            {"role": "user", "content": "讲一个长故事"}
        ]
    ) as stream:
        async for text in stream.text_stream:
            print(text, end="", flush=True)
        print()

三、工具调用(Tool Use)

3.1 基础工具调用

python 复制代码
# ===== 工具调用实战 =====

import json
from anthropic import Anthropic

client = Anthropic()

# 定义可用工具
tools = [
    {
        "name": "get_weather",
        "description": "获取指定城市的天气",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "城市名称,例如:北京"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "温度单位"
                }
            },
            "required": ["city"]
        }
    },
    {
        "name": "search_database",
        "description": "搜索数据库",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "搜索关键词"
                }
            },
            "required": ["query"]
        }
    }
]

# 模拟函数实现
def get_weather(city: str, unit: str = "celsius"):
    """获取天气(模拟)"""
    weather_data = {
        "北京": {"temp": 25, "condition": "晴天"},
        "上海": {"temp": 28, "condition": "多云"}
    }
    data = weather_data.get(city, {"temp": 20, "condition": "未知"})
    return {
        "city": city,
        "temperature": f"{data['temp']}°{'C' if unit == 'celsius' else 'F'}",
        "condition": data['condition']
    }

def search_database(query: str):
    """搜索数据库(模拟)"""
    return [
        {"id": 1, "title": f"关于 {query} 的结果1"},
        {"id": 2, "title": f"关于 {query} 的结果2"}
    ]

# 主流程
def chat_with_tools(user_message: str):
    """带工具调用的对话"""
    messages = [
        {"role": "user", "content": user_message}
    ]
    
    # 第一次调用:让模型决定是否调用工具
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=messages,
        tools=tools
    )
    
    # 检查是否有工具调用
    if response.stop_reason == "tool_use":
        # 添加助手消息(包含工具调用)
        messages.append({
            "role": "assistant",
            "content": response.content
        })
        
        # 执行工具调用
        for content_block in response.content:
            if content_block.type == "tool_use":
                tool_name = content_block.name
                tool_input = content_block.input
                tool_use_id = content_block.id
                
                # 调用对应函数
                if tool_name == "get_weather":
                    result = get_weather(**tool_input)
                elif tool_name == "search_database":
                    result = search_database(**tool_input)
                else:
                    result = {"error": "Unknown function"}
                
                # 添加工具结果
                messages.append({
                    "role": "user",
                    "content": [
                        {
                            "type": "tool_result",
                            "tool_use_id": tool_use_id,
                            "content": json.dumps(result, ensure_ascii=False)
                        }
                    ]
                })
        
        # 第二次调用:让模型根据工具结果生成回复
        final_response = client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1024,
            messages=messages
        )
        
        return final_response.content[0].text
    
    # 没有工具调用,直接返回回复
    return response.content[0].text

# 测试
if __name__ == '__main__':
    result = chat_with_tools("北京今天天气怎么样?")
    print(result)

3.2 并行工具调用

python 复制代码
# ===== 并行工具调用 =====

# Claude 支持一次调用多个工具

tools = [
    {
        "name": "get_weather",
        "description": "获取天气",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {"type": "string"}
            },
            "required": ["city"]
        }
    },
    {
        "name": "get_news",
        "description": "获取新闻",
        "input_schema": {
            "type": "object",
            "properties": {
                "topic": {"type": "string"}
            },
            "required": ["topic"]
        }
    }
]

def parallel_tool_calls():
    messages = [
        {"role": "user", "content": "北京天气怎么样?今天有什么科技新闻?"}
    ]
    
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=messages,
        tools=tools
    )
    
    # 检查是否包含多个工具调用
    tool_uses = [c for c in response.content if c.type == "tool_use"]
    
    if len(tool_uses) > 1:
        print(f"模型并行调用了 {len(tool_uses)} 个工具:")
        for tu in tool_uses:
            print(f"  - {tu.name}: {tu.input}")
        
        # 并行执行(实际可以用 asyncio 并行)
        results = {}
        for tu in tool_uses:
            func_name = tu.name
            func_input = tu.input
            
            if func_name == "get_weather":
                results[tu.id] = get_weather(**func_input)
            elif func_name == "get_news":
                results[tu.id] = get_news(**func_input)
        
        return results

3.3 工具调用最佳实践

python 复制代码
# ===== 工具调用最佳实践 =====

# 1. 工具描述要清晰
tools_good = [
    {
        "name": "get_weather",
        "description": "获取指定城市的当前天气信息,包括温度、天气状况、湿度等。",  # 清晰描述
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "城市名称,支持中英文,例如:北京、Beijing"
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "温度单位,celsius 为摄氏度,fahrenheit 为华氏度"
                }
            },
            "required": ["city"]
        }
    }
]

# 2. 处理工具错误
def handle_tool_error():
    messages = [{"role": "user", "content": "获取北京天气"}]
    
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=messages,
        tools=tools
    )
    
    if response.stop_reason == "tool_use":
        messages.append({
            "role": "assistant",
            "content": response.content
        })
        
        for content_block in response.content:
            if content_block.type == "tool_use":
                try:
                    # 执行工具
                    result = execute_tool(content_block.name, content_block.input)
                    
                    messages.append({
                        "role": "user",
                        "content": [
                            {
                                "type": "tool_result",
                                "tool_use_id": content_block.id,
                                "content": json.dumps(result, ensure_ascii=False)
                            }
                        ]
                    })
                except Exception as e:
                    # 返回错误给模型
                    messages.append({
                        "role": "user",
                        "content": [
                            {
                                "type": "tool_result",
                                "tool_use_id": content_block.id,
                                "content": f"错误: {str(e)}",
                                "is_error": True  # 标记为错误
                            }
                        ]
                    })
        
        # 继续对话
        final_response = client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1024,
            messages=messages
        )
        
        return final_response.content[0].text

# 3. 限制工具调用次数(防止无限循环)
def limit_tool_calls(user_message: str, max_iterations: int = 5):
    """限制工具调用次数"""
    messages = [{"role": "user", "content": user_message}]
    
    for i in range(max_iterations):
        response = client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1024,
            messages=messages,
            tools=tools
        )
        
        if response.stop_reason != "tool_use":
            # 没有工具调用,返回最终回复
            return response.content[0].text
        
        # 处理工具调用
        messages.append({
            "role": "assistant",
            "content": response.content
        })
        
        for content_block in response.content:
            if content_block.type == "tool_use":
                result = execute_tool(content_block.name, content_block.input)
                messages.append({
                    "role": "user",
                    "content": [
                        {
                            "type": "tool_result",
                            "tool_use_id": content_block.id,
                            "content": json.dumps(result, ensure_ascii=False)
                        }
                    ]
                })
    
    # 达到最大迭代次数
    return "达到最大工具调用次数限制"

四、批量处理(Batch API)

4.1 Batch API 使用

python 复制代码
# ===== Batch API 批量处理 =====

from anthropic import Anthropic
import time

client = Anthropic()

# 创建批量任务
def create_batch():
    # 准备批量请求
    requests = [
        {
            "custom_id": "request-1",
            "params": {
                "model": "claude-3-5-haiku-20241022",
                "max_tokens": 1024,
                "messages": [
                    {"role": "user", "content": "1+1=?"}
                ]
            }
        },
        {
            "custom_id": "request-2",
            "params": {
                "model": "claude-3-5-haiku-20241022",
                "max_tokens": 1024,
                "messages": [
                    {"role": "user", "content": "2+2=?"}
                ]
            }
        }
    ]
    
    # 创建批量任务
    batch = client.messages.batches.create(
        requests=requests
    )
    
    batch_id = batch.id
    print(f"Batch ID: {batch_id}")
    print(f"状态: {batch.processing_status}")
    
    return batch_id

# 查询批量任务状态
def check_batch_status(batch_id: str):
    batch = client.messages.batches.retrieve(batch_id)
    
    print(f"状态: {batch.processing_status}")
    print(f"总请求数: {batch.request_counts.processing + batch.request_counts.succeeded + batch.request_counts.errored}")
    print(f"处理中: {batch.request_counts.processing}")
    print(f"成功: {batch.request_counts.succeeded}")
    print(f"失败: {batch.request_counts.errored}")
    
    return batch.processing_status

# 等待批量任务完成
def wait_for_batch(batch_id: str, check_interval: int = 60):
    """等待批量任务完成"""
    while True:
        status = check_batch_status(batch_id)
        
        if status == "ended":
            print("批量任务已完成!")
            break
        elif status == "canceling":
            print("批量任务正在取消...")
            break
        
        print(f"等待 {check_interval} 秒后检查...")
        time.sleep(check_interval)

# 获取批量任务结果
def get_batch_results(batch_id: str):
    """获取批量任务结果"""
    results = []
    
    # 流式读取结果
    for result in client.messages.batches.results(batch_id):
        results.append({
            "custom_id": result.custom_id,
            "success": result.result.type == "succeeded",
            "content": result.result.message.content[0].text if result.result.type == "succeeded" else None,
            "error": result.result.error if result.result.type == "errored" else None
        })
    
    return results

# 完整流程
def batch_processing_example():
    # 1. 创建批量任务
    batch_id = create_batch()
    
    # 2. 等待完成
    wait_for_batch(batch_id)
    
    # 3. 获取结果
    results = get_batch_results(batch_id)
    
    # 4. 处理结果
    for r in results:
        if r["success"]:
            print(f"{r['custom_id']}: {r['content'][:50]}...")
        else:
            print(f"{r['custom_id']}: 错误 - {r['error']}")

4.2 Batch API 最佳实践

python 复制代码
# ===== Batch API 最佳实践 =====

# 1. 合理分批
def optimal_batching(requests: list, batch_size: int = 1000):
    """合理分批"""
    batches = []
    
    for i in range(0, len(requests), batch_size):
        batch_requests = requests[i:i+batch_size]
        
        batch = client.messages.batches.create(
            requests=batch_requests
        )
        
        batches.append(batch.id)
    
    return batches

# 2. 错误处理
def batch_with_error_handling(requests: list):
    """带错误处理的批量处理"""
    batch_id = create_batch_with_requests(requests)
    
    wait_for_batch(batch_id)
    
    results = get_batch_results(batch_id)
    
    succeeded = [r for r in results if r["success"]]
    failed = [r for r in results if not r["success"]]
    
    print(f"成功: {len(succeeded)}")
    print(f"失败: {len(failed)}")
    
    # 重试失败的任务
    if failed:
        print("重试失败的任务...")
        retry_requests = [
            {
                "custom_id": r["custom_id"],
                "params": get_params_by_id(r["custom_id"])  # 需要根据 custom_id 获取原始请求
            }
            for r in failed
        ]
        
        retry_batch_id = create_batch_with_requests(retry_requests)
        wait_for_batch(retry_batch_id)
        retry_results = get_batch_results(retry_batch_id)
        
        return succeeded + retry_results
    
    return succeeded

# 3. 成本优化
def estimate_batch_cost(requests: list):
    """估算批量处理成本"""
    # Batch API 比实时 API 便宜 50%
    # 假设平均每个请求 1000 input tokens + 500 output tokens
    
    avg_input_tokens = 1000
    avg_output_tokens = 500
    num_requests = len(requests)
    
    # Claude 3.5 Haiku 价格
    input_price_per_1m = 1.00  # $1/1M tokens
    output_price_per_1m = 5.00  # $5/1M tokens
    
    total_input_cost = (avg_input_tokens * num_requests / 1_000_000) * input_price_per_1m
    total_output_cost = (avg_output_tokens * num_requests / 1_000_000) * output_price_per_1m
    
    realtime_cost = total_input_cost + total_output_cost
    batch_cost = realtime_cost * 0.5  # Batch API 便宜 50%
    
    print(f"实时 API 成本: ${realtime_cost:.2f}")
    print(f"Batch API 成本: ${batch_cost:.2f}")
    print(f"节省: ${realtime_cost - batch_cost:.2f}")
    
    return batch_cost

五、错误处理与重试

5.1 错误类型

python 复制代码
# ===== Claude API 错误类型 =====

from anthropic import Anthropic
from anthropic._exceptions import (
    APIError,
    APIConnectionError,
    RateLimitError,
    AuthenticationError,
    BadRequestError,
    InternalServerError,
    NotFoundError,
    PermissionDeniedError,
    UnprocessableEntityError,
    OverloadedError
)

client = Anthropic()

def robust_api_call(messages: list, max_retries: int = 3):
    """健壮的 API 调用(带重试)"""
    for attempt in range(max_retries):
        try:
            response = client.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=1024,
                messages=messages,
                timeout=30.0  # 30 秒超时
            )
            return response.content[0].text
        
        except RateLimitError as e:
            # 速率限制
            wait_time = 2 ** attempt  # 指数退避
            print(f"速率限制,{wait_time}秒后重试...")
            time.sleep(wait_time)
        
        except APIConnectionError as e:
            # 网络连接错误
            print(f"网络连接错误: {e}")
            if attempt == max_retries - 1:
                raise
            time.sleep(2)
        
        except InternalServerError as e:
            # Anthropic 服务器错误(500 等)
            print(f"Anthropic 服务器错误: {e}")
            time.sleep(5)
        
        except OverloadedError as e:
            # 服务器过载
            print(f"服务器过载,{2 ** attempt}秒后重试...")
            time.sleep(2 ** attempt)
        
        except AuthenticationError as e:
            # API Key 错误
            print(f"认证失败,请检查 API Key: {e}")
            raise
        
        except BadRequestError as e:
            # 请求参数错误
            print(f"请求参数错误: {e}")
            raise
        
        except Exception as e:
            # 其他错误
            print(f"未知错误: {e}")
            if attempt == max_retries - 1:
                raise
            time.sleep(1)
    
    raise Exception("达到最大重试次数")

5.2 重试装饰器

python 复制代码
# ===== 重试装饰器 =====

import time
import functools
from anthropic._exceptions import RateLimitError, APIConnectionError, InternalServerError, OverloadedError

def retry_on_error(max_retries: int = 3, backoff_factor: float = 2.0):
    """重试装饰器"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except (RateLimitError, APIConnectionError, InternalServerError, OverloadedError) as e:
                    if attempt == max_retries - 1:
                        raise
                    
                    wait_time = backoff_factor ** attempt
                    print(f"错误: {e}, {wait_time}秒后重试...")
                    time.sleep(wait_time)
            
            raise Exception("达到最大重试次数")
        return wrapper
    return decorator

# 使用装饰器
@retry_on_error(max_retries=5, backoff_factor=2.0)
def call_claude_api(messages: list):
    """调用 Claude API"""
    client = Anthropic()
    response = client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=messages
    )
    return response.content[0].text

# 异步版本
import asyncio
from anthropic import AsyncAnthropic

def async_retry_on_error(max_retries: int = 3, backoff_factor: float = 2.0):
    """异步重试装饰器"""
    def decorator(func):
        @functools.wraps(func)
        async def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return await func(*args, **kwargs)
                except (RateLimitError, APIConnectionError, InternalServerError, OverloadedError) as e:
                    if attempt == max_retries - 1:
                        raise
                    
                    wait_time = backoff_factor ** attempt
                    print(f"错误: {e}, {wait_time}秒后重试...")
                    await asyncio.sleep(wait_time)
            
            raise Exception("达到最大重试次数")
        return wrapper
    return decorator

@async_retry_on_error(max_retries=5)
async def async_call_claude(messages: list):
    """异步调用 Claude API"""
    client = AsyncAnthropic()
    response = await client.messages.create(
        model="claude-3-5-sonnet-20241022",
        max_tokens=1024,
        messages=messages
    )
    return response.content[0].text

六、成本控制

6.1 Token 计算

python 复制代码
# ===== Token 计算 =====

import tiktoken
from anthropic import Anthropic

client = Anthropic()

def count_tokens(text: str):
    """计算文本的 token 数(使用 tiktoken 近似)"""
    # Claude 使用自己的 tokenizer,但这里用 tiktoken 近似
    # cl100k_base 是 GPT-4 的 tokenizer,可以作为近似
    encoding = tiktoken.get_encoding("cl100k_base")
    tokens = encoding.encode(text)
    return len(tokens)

def estimate_cost(input_text: str, output_text: str, model: str = "claude-3-5-sonnet-20241022"):
    """估算成本"""
    pricing = {
        "claude-3-5-sonnet-20241022": {"input": 3.00, "output": 15.00},
        "claude-3-5-haiku-20241022": {"input": 1.00, "output": 5.00},
        "claude-3-opus-20240229": {"input": 15.00, "output": 75.00},
        "claude-3-sonnet-20240229": {"input": 3.00, "output": 15.00},
        "claude-3-haiku-20240307": {"input": 0.25, "output": 1.25}
    }
    
    if model not in pricing:
        return None
    
    input_tokens = count_tokens(input_text)
    output_tokens = count_tokens(output_text)
    
    input_cost = (input_tokens / 1_000_000) * pricing[model]["input"]
    output_cost = (output_tokens / 1_000_000) * pricing[model]["output"]
    
    total_cost = input_cost + output_cost
    
    return {
        "input_tokens": input_tokens,
        "output_tokens": output_tokens,
        "input_cost_usd": input_cost,
        "output_cost_usd": output_cost,
        "total_cost_usd": total_cost
    }

# 监控 token 使用
def track_token_usage(response):
    """跟踪 token 使用"""
    usage = response.usage
    print(f"输入 tokens: {usage.input_tokens}")
    print(f"输出 tokens: {usage.output_tokens}")
    
    # 计算成本
    cost = estimate_cost("", "", model="claude-3-5-sonnet-20241022")  # 需要根据实际使用计算
    return usage

6.2 成本优化策略

python 复制代码
# ===== 成本优化策略 =====

from anthropic import Anthropic
import tiktoken

client = Anthropic()

# 策略 1:使用更便宜的模型
def use_cheaper_model():
    """简单任务使用便宜模型"""
    response = client.messages.create(
        model="claude-3-5-haiku-20241022",  # 比 Sonnet 便宜 3 倍
        max_tokens=1024,
        messages=[
            {"role": "user", "content": "1+1=?"}
        ]
    )
    return response.content[0].text

# 策略 2:减少输入 token(压缩上下文)
def compress_context(messages: list, max_tokens: int = 4096):
    """压缩上下文"""
    # 保留系统消息
    system_msgs = [m for m in messages if m.get("role") == "system"]
    
    # 保留最近的对话
    recent_msgs = [m for m in messages if m.get("role") != "system"]
    recent_msgs = recent_msgs[-10:]  # 只保留最近 10 条
    
    # 合并
    compressed = system_msgs + recent_msgs
    
    # 检查 token 数
    total_tokens = sum(count_tokens(str(m)) for m in compressed)
    if total_tokens > max_tokens:
        # 进一步压缩
        compressed = system_msgs + recent_msgs[-5:]
    
    return compressed

# 策略 3:使用缓存(避免重复调用)
import hashlib
import json
import os

class CachedClaude:
    """带缓存的 Claude 客户端"""
    def __init__(self, cache_dir: str = ".claude_cache"):
        self.client = Anthropic()
        self.cache_dir = cache_dir
        os.makedirs(cache_dir, exist_ok=True)
    
    def _cache_key(self, messages: list, model: str):
        """生成缓存 key"""
        content = json.dumps({"messages": messages, "model": model}, ensure_ascii=False)
        return hashlib.md5(content.encode()).hexdigest()
    
    def _get_cache(self, cache_key: str):
        """获取缓存"""
        cache_path = os.path.join(self.cache_dir, f"{cache_key}.json")
        if os.path.exists(cache_path):
            with open(cache_path, 'r', encoding='utf-8') as f:
                return json.load(f)
        return None
    
    def _set_cache(self, cache_key: str, response):
        """设置缓存"""
        cache_path = os.path.join(self.cache_dir, f"{cache_key}.json")
        with open(cache_path, 'w', encoding='utf-8') as f:
            json.dump(response, f, ensure_ascii=False)
    
    def chat(self, messages: list, model: str = "claude-3-5-sonnet-20241022"):
        """带缓存的对话"""
        cache_key = self._cache_key(messages, model)
        
        # 检查缓存
        cached = self._get_cache(cache_key)
        if cached:
            print("使用缓存")
            return cached
        
        # 调用 API
        response = self.client.messages.create(
            model=model,
            max_tokens=1024,
            messages=messages
        )
        
        result = response.content[0].text
        
        # 写入缓存
        self._set_cache(cache_key, result)
        
        return result

# 策略 4:使用 Batch API(便宜 50%)
def use_batch_api(requests: list):
    """使用 Batch API"""
    # 见第四章
    pass

七、生产案例

7.1 案例:智能代码审查系统

python 复制代码
# ===== 案例:智能代码审查系统 =====

from anthropic import Anthropic
import os

client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

class CodeReviewBot:
    """智能代码审查机器人"""
    
    def __init__(self):
        self.client = client
        self.review_history = []
        
        # 定义工具
        self.tools = [
            {
                "name": "get_file_content",
                "description": "获取文件内容",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "file_path": {
                            "type": "string",
                            "description": "文件路径"
                        }
                    },
                    "required": ["file_path"]
                }
            },
            {
                "name": "run_linter",
                "description": "运行代码检查工具(如 pylint、eslint)",
                "input_schema": {
                    "type": "object",
                    "properties": {
                        "file_path": {
                            "type": "string",
                            "description": "文件路径"
                        }
                    },
                    "required": ["file_path"]
                }
            }
        ]
    
    def get_file_content(self, file_path: str):
        """获取文件内容(模拟)"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                return f.read()
        except Exception as e:
            return {"error": str(e)}
    
    def run_linter(self, file_path: str):
        """运行代码检查(模拟)"""
        # 实际应该调用 pylint、eslint 等
        return {
            "file": file_path,
            "issues": [
                {"line": 10, "message": "未使用的变量"},
                {"line": 25, "message": "函数过长"}
            ]
        }
    
    def review_code(self, pr_description: str, file_paths: list):
        """审查代码"""
        # 构建消息
        messages = [
            {
                "role": "user",
                "content": f"请审查以下 Pull Request:\n\n{pr_description}\n\n文件列表:{', '.join(file_paths)}"
            }
        ]
        
        # 调用 API
        response = self.client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=2048,
            messages=messages,
            tools=self.tools
        )
        
        # 处理工具调用
        if response.stop_reason == "tool_use":
            messages.append({
                "role": "assistant",
                "content": response.content
            })
            
            for content_block in response.content:
                if content_block.type == "tool_use":
                    tool_name = content_block.name
                    tool_input = content_block.input
                    tool_use_id = content_block.id
                    
                    # 执行工具
                    if tool_name == "get_file_content":
                        result = self.get_file_content(**tool_input)
                    elif tool_name == "run_linter":
                        result = self.run_linter(**tool_input)
                    else:
                        result = {"error": "Unknown tool"}
                    
                    # 添加工具结果
                    messages.append({
                        "role": "user",
                        "content": [
                            {
                                "type": "tool_result",
                                "tool_use_id": tool_use_id,
                                "content": json.dumps(result, ensure_ascii=False)
                            }
                        ]
                    })
            
            # 生成最终审查意见
            final_response = self.client.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=2048,
                messages=messages
            )
            
            review = final_response.content[0].text
            self.review_history.append({
                "pr": pr_description,
                "review": review
            })
            
            return review
        
        # 没有工具调用
        return response.content[0].text

# 使用
if __name__ == '__main__':
    bot = CodeReviewBot()
    
    pr_desc = "修复了用户登录的 bug,添加了输入验证"
    files = ["src/auth.py", "tests/test_auth.py"]
    
    review = bot.review_code(pr_desc, files)
    print(f"代码审查意见:\n{review}")

7.2 案例:文档智能问答系统

python 复制代码
# ===== 案例:文档智能问答系统 =====

from anthropic import Anthropic
import os

client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

class DocumentQA:
    """文档智能问答系统"""
    
    def __init__(self, documents: list):
        self.client = client
        self.documents = documents
        self.embeddings = self._compute_embeddings(documents)
    
    def _compute_embeddings(self, documents: list):
        """计算文档向量(简化版,实际应使用 Embeddings API)"""
        # 实际应该使用 OpenAI/Azure 的 Embeddings API
        # 这里简化为使用字符数作为向量
        return [len(doc) for doc in documents]
    
    def _semantic_search(self, query: str, top_k: int = 3):
        """语义搜索(简化版)"""
        # 实际应该使用向量相似度
        # 这里简化为关键词匹配
        results = []
        for i, doc in enumerate(self.documents):
            if query.lower() in doc.lower():
                results.append((i, doc[:200]))
        
        return results[:top_k]
    
    def answer_question(self, question: str):
        """回答问题"""
        # 1. 检索相关文档
        relevant_docs = self._semantic_search(question, top_k=3)
        
        if not relevant_docs:
            return "抱歉,没有找到相关文档。"
        
        # 2. 构建上下文
        context = "\n\n".join([
            f"文档 {i+1}:{doc}" for i, doc in relevant_docs
        ])
        
        # 3. 构建提示
        messages = [
            {
                "role": "user",
                "content": f"""请根据以下文档回答问题。

文档:
{context}

问题:{question}

要求:
1. 只根据文档内容回答
2. 如果文档中没有相关信息,说"文档中没有相关信息"
3. 引用文档中的具体内容"""
            }
        ]
        
        # 4. 调用 API
        response = self.client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1024,
            messages=messages
        )
        
        return response.content[0].text

# 使用
if __name__ == '__main__':
    # 初始化文档
    docs = [
        "OpenAI API 是 OpenAI 提供的接口,支持文本生成、图像生成等功能。",
        "Claude API 是 Anthropic 提供的接口,擅长代码生成和文档分析。",
        "向量数据库用于存储 Embeddings,支持语义搜索。"
    ]
    
    qa = DocumentQA(docs)
    
    # 问答
    question = "OpenAI API 有什么功能?"
    answer = qa.answer_question(question)
    print(f"问:{question}")
    print(f"答:{answer}")

八、总结

8.1 核心要点

#mermaid-svg-vjQ3GVflsF3rwxN5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vjQ3GVflsF3rwxN5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vjQ3GVflsF3rwxN5 .error-icon{fill:#552222;}#mermaid-svg-vjQ3GVflsF3rwxN5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vjQ3GVflsF3rwxN5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vjQ3GVflsF3rwxN5 .marker.cross{stroke:#333333;}#mermaid-svg-vjQ3GVflsF3rwxN5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vjQ3GVflsF3rwxN5 p{margin:0;}#mermaid-svg-vjQ3GVflsF3rwxN5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-vjQ3GVflsF3rwxN5 .cluster-label text{fill:#333;}#mermaid-svg-vjQ3GVflsF3rwxN5 .cluster-label span{color:#333;}#mermaid-svg-vjQ3GVflsF3rwxN5 .cluster-label span p{background-color:transparent;}#mermaid-svg-vjQ3GVflsF3rwxN5 .label text,#mermaid-svg-vjQ3GVflsF3rwxN5 span{fill:#333;color:#333;}#mermaid-svg-vjQ3GVflsF3rwxN5 .node rect,#mermaid-svg-vjQ3GVflsF3rwxN5 .node circle,#mermaid-svg-vjQ3GVflsF3rwxN5 .node ellipse,#mermaid-svg-vjQ3GVflsF3rwxN5 .node polygon,#mermaid-svg-vjQ3GVflsF3rwxN5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vjQ3GVflsF3rwxN5 .rough-node .label text,#mermaid-svg-vjQ3GVflsF3rwxN5 .node .label text,#mermaid-svg-vjQ3GVflsF3rwxN5 .image-shape .label,#mermaid-svg-vjQ3GVflsF3rwxN5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-vjQ3GVflsF3rwxN5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vjQ3GVflsF3rwxN5 .rough-node .label,#mermaid-svg-vjQ3GVflsF3rwxN5 .node .label,#mermaid-svg-vjQ3GVflsF3rwxN5 .image-shape .label,#mermaid-svg-vjQ3GVflsF3rwxN5 .icon-shape .label{text-align:center;}#mermaid-svg-vjQ3GVflsF3rwxN5 .node.clickable{cursor:pointer;}#mermaid-svg-vjQ3GVflsF3rwxN5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vjQ3GVflsF3rwxN5 .arrowheadPath{fill:#333333;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vjQ3GVflsF3rwxN5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vjQ3GVflsF3rwxN5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vjQ3GVflsF3rwxN5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vjQ3GVflsF3rwxN5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vjQ3GVflsF3rwxN5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vjQ3GVflsF3rwxN5 .cluster text{fill:#333;}#mermaid-svg-vjQ3GVflsF3rwxN5 .cluster span{color:#333;}#mermaid-svg-vjQ3GVflsF3rwxN5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vjQ3GVflsF3rwxN5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vjQ3GVflsF3rwxN5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-vjQ3GVflsF3rwxN5 .icon-shape,#mermaid-svg-vjQ3GVflsF3rwxN5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vjQ3GVflsF3rwxN5 .icon-shape p,#mermaid-svg-vjQ3GVflsF3rwxN5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vjQ3GVflsF3rwxN5 .icon-shape .label rect,#mermaid-svg-vjQ3GVflsF3rwxN5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vjQ3GVflsF3rwxN5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vjQ3GVflsF3rwxN5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vjQ3GVflsF3rwxN5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Claude API 实战
基础调用
高级特性
批量处理
生产实践
模型选择
Messages API
参数调优
工具调用
Vision
流式响应
Batch API
成本优化
错误处理
重试机制
监控告警

8.2 最佳实践

实践 说明
模型选择 简单任务用 Haiku,复杂任务用 Sonnet/Opus
工具调用 让模型调用外部工具,增强能力
流式响应 提升用户体验,减少等待感
错误处理 实现重试机制,处理速率限制
成本控制 使用 Batch API、缓存、便宜模型
Vision 支持图片理解,但需 Base64 编码

8.3 成本优化

策略 节省
使用 Haiku 比 Sonnet 便宜 3 倍
Batch API 比实时 API 便宜 50%
缓存结果 避免重复调用
压缩上下文 减少输入 token
限制 max_tokens 控制输出长度

本文基于 Claude API 官方文档编写。如有问题欢迎评论区讨论!

相关推荐
VIP_CQCRE6 小时前
Claude 接入 Luma MCP:一句话让 AI 生成电影感短视频
ai·claude·mcp·luma·acedatacloud
Ai思想家6 小时前
私有化部署的服务器选型与容量规划
人工智能·安全·ai
aiqianji7 小时前
一键生成AI短篇小说的写作软件有哪些?
ai
寅时码8 小时前
我的 AI 工作流写了两年,直到 Opus 4.8 才真正生效
openai·ai编程·claude
阿文和她的Key11 小时前
DeepSeek API 涨价背后的三层供给瓶颈
人工智能·ai
鬼手点金12 小时前
Hermes Agent vs OpenCode 异同
ai·ai agent·vibecoding·codingagent·opencode·hermes
xcLeigh12 小时前
编程语言的 AI 友好度排名:Python、JavaScript、TypeScript 谁更适合 AI 辅助
javascript·人工智能·python·ai·typescript·ai编程
wang_yb14 小时前
用递归消除法优化“特征子集”
ai·databook
维核科技14 小时前
Llama 3.3 vs Qwen2.5 vs DeepSeek-R1
ai·私有化部署·llama·大模型部署·私有化大模型部署
lifallen15 小时前
Emdash 拆解:多 Agent 并行开发桌面端的实现思路,兼谈 ACP 与 A2A
人工智能·学习·ai·ai编程