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 官方文档编写。如有问题欢迎评论区讨论!

相关推荐
真上帝的左手2 小时前
19. 大数据- BI - AI 应用2-AI模型部署与企业落地
大数据·人工智能·ai·bi
万能的知了2 小时前
Cursor、Windsurf、Copilot 横评:一个月深度使用体验
ai·copilot·ai编程
webmote2 小时前
从零打造虚拟小智:用浏览器模拟 IoT 设备的实践之路
物联网·websocket·ai·大模型·llm·.net·小智
Fine姐3 小时前
Claude Code 安装失败claude-code-releases/latest after 3 attempt
ai
Esaka_Forever3 小时前
Rag中的indexing是什么意思
ai
清欢渡hb3 小时前
一人 AI 软件公司 · Claude Code 插件架构设计
人工智能·ai编程·claude·一人公司
七夜zippoe3 小时前
OpenClaw Nodes 设备管理深度解析:AI Agent的跨设备协作能力
人工智能·ai·agent·openclaw·nodes
小肥君3 小时前
模型比对gpt5.4nano
ai
AI探索先锋3 小时前
[特殊字符] GPT-5.6 偷跑实锤!Anthropic 边喊“刹车“边冲 IPO,一只“哥布林“让 OpenAI 连夜封号|AI科技热线
人工智能·科技·ai