我把 Anthropic 官方的 Claude Cookbook 拆成了 30+ 个能直接跑的例子

下面这套内容基于 Anthropic 公开 API 和官方 claude-cookbooks 仓库整理,所有代码都能直接运行。如果你也想知道 Claude 到底能干什么、代码怎么写、坑在哪里,这篇应该能省你不少时间。

前言

Anthropic 有个 GitHub 仓库叫 claude-cookbooks,里面塞了 30 多个 Notebook,工具调用、扩展思考、多模态、RAG、Agent 都覆盖了。

我自己翻过一遍,感觉有两个地方不太顺手:

一是太散。每个能力一个独立文件,看完记得住语法,串不起主线。

二是太碎。不少例子只给片段,复制到本地跑不通,坑得自己踩。

后来我按"能直接用"的思路重排了一遍,把主线捋顺,每段都补上能跑的代码。下面就是整理后的结果。读到后面,你应该能自己拼出一个会查资料、会算账、能看图、还能多步推理的 Agent。

前置:会一点 Python(函数、字典、循环够用),有一个 Anthropic API Key。不用懂机器学习。

读完能动手做这些:

  • 工具调用:让 Claude 去调你写的任意函数,比如查天气、算账、查数据库
  • 扩展思考:开起来处理复杂推理和多步任务
  • 视觉:让 Claude 读图、读图表、读文档
  • RAG:把自己的文档接进 Claude 做问答
  • 多智能体:用编排器、评估-优化这些模式搭一套系统

0. 环境准备

装 SDK 和配 Key

bash 复制代码
pip install anthropic

export ANTHROPIC_API_KEY="sk-ant-..."   # macOS / Linux
# set ANTHROPIC_API_KEY=sk-ant-...      # Windows PowerShell

提醒:别把 Key 写进会提交到 Git 的代码里。用 .env 加 python-dotenv,或者直接用系统环境变量。泄露了马上去控制台吊销。

封装一个好用的 client

官方 SDK 调用很直白,但每次写一堆参数有点啰嗦。教程里统一用下面这个封装,之后所有示例都基于它。

python 复制代码
import os
import anthropic

# 模型名随版本更新;3.7 Sonnet 支持扩展思考,4 系也支持。
# 用最新模型时替换为 claude-sonnet-4-... / claude-opus-4-... 等。
MODEL = "claude-3-7-sonnet-latest"

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

def chat(prompt, system=None, max_tokens=1024):
    """最简单的对话:发一句话,拿回文字。"""
    messages = [{"role": "user", "content": prompt}]
    kwargs = {"model": MODEL, "max_tokens": max_tokens, "messages": messages}
    if system:
        kwargs["system"] = system
    resp = client.messages.create(**kwargs)
    return resp.content[0].text

print(chat("用一句话解释什么是大模型。"))

能打印出一段中文解释,说明 Key、网络、SDK 都没问题。报错的话:401 是 Key 不对,429 是额度或限流,404 多半是模型名拼错。

1. 核心概念

写工具调用前,先把三个概念理顺,后面代码都围绕它们:

概念 是什么 在代码里长啥样
Messages 一次对话由多条 message 组成,每条带 role(user/assistant)和 content [{"role":"user","content":"你好"}]
Content Blocks 一条 message 的 content 可以是字符串,也可以是多个结构化块:text / tool_use / tool_result / thinking / image [{"type":"text","text":"..."}]
Tools 你声明的"函数清单",含名称、描述、JSON Schema 参数。Claude 决定何时调用 tools=[{"name":...,"input_schema":{...}}]

工具调用真正关键的地方在于它是一个来回的过程:你把 tools 给模型,模型返回 tool_use 块(只说想调哪个函数、参数是什么,不会真去执行),你执行完函数,把结果用 tool_result 块喂回去,模型再接着回答。后面所有 Agent 都是这个骨架。

2. Tool Use 工具调用

Tool Use 是 Claude 最核心的能力:把你自己写的真实函数交给模型,模型在需要的时候用正确的参数去调用。下面从最小例子一路讲到并行、记忆、精确计算。

2.1 你的第一个工具:查天气

流程分六步:声明工具(名字+描述+参数 Schema),把工具和用户问题一起发给模型,模型返回 tool_use 块,你执行函数,把结果作为 tool_result 回传,模型给出最终回答。

python 复制代码
import anthropic, os
client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
MODEL = "claude-3-7-sonnet-latest"

weather_tool = {
    "name": "get_weather",
    "description": "获取指定城市的当前天气",
    "input_schema": {
        "type": "object",
        "properties": {
            "city": {"type": "string", "description": "城市名,如 '北京'"}
        },
        "required": ["city"]
    }
}

def get_weather(city):
    # 真实场景这里会请求天气 API;此处用模拟数据演示
    return {"city": city, "temp_c": 22, "condition": "晴"}

messages = [{"role": "user", "content": "北京今天天气怎么样?"}]
resp = client.messages.create(
    model=MODEL, max_tokens=1024,
    tools=[weather_tool], messages=messages
)

# 取出模型想调用的工具
tool_use = next(b for b in resp.content if b.type == "tool_use")
result = get_weather(**tool_use.input)   # 真正执行函数

# 把结果回传:assistant 原样保留,user 补上 tool_result
messages.append({"role": "assistant", "content": resp.content})
messages.append({"role": "user", "content": [{
    "type": "tool_result",
    "tool_use_id": tool_use.id,
    "content": str(result)
}]})
final = client.messages.create(
    model=MODEL, max_tokens=1024,
    tools=[weather_tool], messages=messages
)
print(final.content[0].text)

坑:回传时 assistant 这条必须原样放整个 resp.content(包括 tool_use 块),不能只留文字。不然模型不知道自己在等哪个工具的结果。

2.2 控制工具选择:tool_choice

默认 tool_choice 是 {"type":"auto"},模型自己决定调不调、调哪个。另外两个模式:

模式 行为 用途
auto 模型自由决定 常规对话
any 本轮必须调用某个工具(不确定哪个) 强制走工具流程
tool 强制调用指定工具:{"type":"tool","name":"get_weather"} 确定性流程 / 评测
python 复制代码
# 强制调用指定工具(用于结构化抽取、评测等确定场景)
resp = client.messages.create(
    model=MODEL, max_tokens=1024,
    tools=[weather_tool],
    tool_choice={"type": "tool", "name": "get_weather"},
    messages=[{"role": "user", "content": "上海"}]
)
print(resp.content[0].input)   # 直接拿到结构化参数 {"city": "上海"}

2.3 结构化 JSON 抽取(Pydantic)

把 Pydantic 模型当抽取模板用:模型的字段生成工具的 input_schema,拿到 tool_use 之后直接 model_validate 成对象,类型安全还能顺带校验。

python 复制代码
from pydantic import BaseModel
from typing import List

class Person(BaseModel):
    name: str
    age: int
    skills: List[str]

# 由 Pydantic 模型生成工具定义
extract_tool = {
    "name": "extract_person",
    "description": "从文本中抽取人物信息",
    "input_schema": Person.model_json_schema()
}

text = "李雷,28 岁,会 Python 和 SQL。"
resp = client.messages.create(
    model=MODEL, max_tokens=1024,
    tools=[extract_tool],
    tool_choice={"type": "tool", "name": "extract_person"},
    messages=[{"role": "user", "content": text}]
)
block = next(b for b in resp.content if b.type == "tool_use")
person = Person.model_validate(block.input)   # 带校验地转成对象
print(person.name, person.age, person.skills)

这比让模型直接吐 JSON 再用 json.loads 稳。字段缺了、类型错了,Pydantic 会直接拦下来,而且你拿到的是对象,不是字符串。

2.4 并行工具调用

模型可以在一次回复里发出多个 tool_use 块。处理方式和单次差不多,只是要把每个工具都跑一遍,再一次性把所有 tool_result 回传。

python 复制代码
tools = [weather_tool]   # 假设还有 get_stock、get_news 等多个工具
def dispatch(name, args):
    if name == "get_weather": return get_weather(**args)
    # ... 其它工具
    return {"error": f"unknown tool {name}"}

messages = [{"role": "user", "content": "北京天气和腾讯股价分别是多少?"}]
resp = client.messages.create(model=MODEL, max_tokens=1024, tools=tools, messages=messages)

tool_results = []
for b in resp.content:
    if b.type == "tool_use":
        tool_results.append({
            "type": "tool_result",
            "tool_use_id": b.id,
            "content": str(dispatch(b.name, b.input))
        })
messages.append({"role": "assistant", "content": resp.content})
messages.append({"role": "user", "content": tool_results})
final = client.messages.create(model=MODEL, max_tokens=1024, tools=tools, messages=messages)
print(final.content[0].text)

2.5 持久化记忆(Memory)

长对话会变长、变贵,模型也容易"忘事"。两个办法比较实用:把旧消息压成摘要,或者把关键事实抽出来存库,要用的时候再塞回 system。

python 复制代码
def compress_history(messages, keep_last=4):
    """把较早的消息压缩成一段摘要,保留最近 keep_last 轮。"""
    if len(messages) <= keep_last:
        return messages
    old, recent = messages[:-keep_last], messages[-keep_last:]
    summary = chat(
        "请把以下对话压缩成 3 句话的关键信息摘要:\n" + str(old),
        max_tokens=300
    )
    return [{"role": "user", "content": f"[历史摘要] {summary}"}] + recent

def extract_facts(text):
    """把用户刚说的话里的事实抽成列表(很简单的关键信息提取)。"""
    facts = chat(
        "从下面文字抽取关键事实,每行一条,不要解释:\n" + text,
        max_tokens=300
    )
    return [line for line in facts.splitlines() if line.strip()]

# 用法示例
memory = []
memory += extract_facts("用户叫 tuo,在做 AI 助手开发。")
messages = compress_history(messages)
system = "已知用户背景:" + ";".join(memory)

真实产品里 memory 通常落库(SQLite / 向量库)。这里只给最小可运行骨架,存储你照着接就行。

2.6 计算器工具:补上模型的数学短板

大模型做精确算术、大数运算容易出错。把计算交给真正的 Python,模型只负责决定算什么。

python 复制代码
calc_tool = {
    "name": "calculator",
    "description": "精确计算数学表达式,支持 + - * / 和括号",
    "input_schema": {
        "type": "object",
        "properties": {"expression": {"type": "string", "description": "如 '(12+8)*3/2'"}},
        "required": ["expression"]
    }
}

def calculator(expression):
    # 仅允许安全字符,避免 eval 风险
    allowed = set("0123456789+-*/(). ")
    if not set(expression) <= allowed:
        return {"error": "非法字符"}
    try:
        return {"result": eval(expression, {"__builtins__": {}})}
    except Exception as e:
        return {"error": str(e)}

# 与 2.4 的 dispatch 思路一致:模型产出表达式 -> 你 eval -> 回传结果

这里用白名单字符加清空 builtins 来降低 eval 风险。真要上生产,建议用 asteval 或 sympy 这类安全表达式库。

3. Extended Thinking 扩展思考

扩展思考让模型在回答之前先想一会儿,把推理过程写进 thinking 块。数学、规划、多步推理这类任务开着会明显更稳。注意两点:开了之后 max_tokens 必须大于 budget_tokens,而且 thinking 块要原样回传。

3.1 基础用法

python 复制代码
resp = client.messages.create(
    model=MODEL,
    max_tokens=4096,                       # 必须 > budget_tokens
    thinking={"type": "enabled", "budget_tokens": 2048},
    messages=[{"role": "user",
               "content": "一个游泳池长 25 米、宽 10 米、深 2 米,注满需要多少吨水?(1 立方米水=1 吨)"}]
)
for b in resp.content:
    if b.type == "thinking":
        print("【思考】", b.thinking)
    elif b.type == "text":
        print("【答案】", b.text)

budget_tokens 越大,思考越深、越慢、也越贵。简单题给小一点(5121024),难题给大(20488000)。不是越大越好。

3.2 思考 + 工具调用(Agent 核心)

让模型边想边调工具,是高级 Agent 的关键写法。回传时有个坑:把 tool_result 发回去的时候,上一轮 assistant 的完整 content(包括 thinking 块)必须原样带上,否则直接报错。

python 复制代码
tools = [weather_tool, calc_tool]

messages = [{"role": "user",
             "content": "北京比上海平均气温高几度?查天气后算差值。"}]

for _ in range(5):   # 最多 5 轮,防止死循环
    resp = client.messages.create(
        model=MODEL, max_tokens=4096,
        thinking={"type": "enabled", "budget_tokens": 2048},
        tools=tools, messages=messages
    )
    messages.append({"role": "assistant", "content": resp.content})  # 含 thinking 块,原样保留

    # 没有工具调用 = 已得出最终答案
    if not any(b.type == "tool_use" for b in resp.content):
        break

    results = []
    for b in resp.content:
        if b.type == "tool_use":
            fn = get_weather if b.name == "get_weather" else calculator
            results.append({"type": "tool_result", "tool_use_id": b.id,
                            "content": str(fn(**b.input))})
    messages.append({"role": "user", "content": results})

print(messages[-1].content[0].text)

必须原样保留 thinking 块,这是 90% 报错的地方。只要开了 thinking,assistant 这条就放整个 resp.content,别只挑 tool_use 放。

4. 多模态 Vision

Claude 能直接看图片:把图片以 base64 放进 content 块就行。支持的图片类型:png / jpeg / gif / webp。

4.1 图片输入

python 复制代码
import base64

def load_image(path):
    with open(path, "rb") as f:
        data = base64.b64encode(f.read()).decode()
    # 按实际类型改 media_type:image/png / image/jpeg / image/gif / image/webp
    return {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": data}}

resp = client.messages.create(
    model=MODEL, max_tokens=1024,
    messages=[{"role": "user", "content": [
        {"type": "text", "text": "图里有什么?请详细描述。"},
        load_image("example.png")
    ]}]
)
print(resp.content[0].text)

4.2 读图表 / 文档

图表、PPT、扫描件都能喂给模型做视觉理解。几个让准确率上去的习惯:图要清晰、对比度高;prompt 里说清你要什么(只要表格数据,还是要结论);多页文档分页传,逐页处理完再汇总。

python 复制代码
def read_chart(path, ask="请提取图中的关键数据并简要说明趋势。"):
    resp = client.messages.create(
        model=MODEL, max_tokens=1500,
        messages=[{"role": "user", "content": [
            {"type": "text", "text": ask},
            load_image(path)
        ]}]
    )
    return resp.content[0].text

# 多页文档:逐页抽文字后拼接
pages_text = [read_chart(f"doc_p{i}.png", "只抽取本页全部文字,保留段落。") for i in range(1, 4)]
full = "\n".join(pages_text)
summary = chat(f"请总结以下文档要点:\n{full}", max_tokens=800)

5. RAG 检索增强生成

RAG 的思路是先检索相关资料,再让 Claude 基于资料回答,解决模型不知道你私有数据的问题。四步:分块、嵌入、检索、拼装。

Anthropic 官方已经不提供通用文本 Embedding 接口。检索环节的向量化得用第三方,官方自己推荐 Voyage AI(pip install voyageai)。下面用可插拔的 embed() 演示,你换成任意提供商都行。

python 复制代码
import math, re

def chunk_text(text, size=500, overlap=50):
    """简单按字符滑动窗口分块。生产可用按句子/段落切。"""
    step = size - overlap
    return [text[i:i+size] for i in range(0, len(text), step)]

def embed(text):
    """占位:替换为 Voyage / OpenAI 等真实嵌入。返回向量 list[float]。"""
    # 真实调用示例(需装 voyageai 并设 VOYAGE_API_KEY):
    # import voyageai; v = voyageai.Client(); return v.embed(text, model="voyage-3").embeddings[0]
    return [float(hash(text[i:i+4]) % 1000) / 1000 for i in range(0, 256)]  # 演示用伪向量

def cosine(a, b):
    dot = sum(x*y for x, y in zip(a, b))
    na = math.sqrt(sum(x*x for x in a)); nb = math.sqrt(sum(y*y for y in b))
    return dot / (na * nb)

# 建库
docs = chunk_text(open("手册.txt", encoding="utf-8").read())
index = [(c, embed(c)) for c in docs]

def retrieve(query, top_k=3):
    qv = embed(query)
    ranked = sorted(index, key=lambda x: cosine(x[1], qv), reverse=True)
    return [c for c, _ in ranked[:top_k]]

# 问答
def rag_answer(question):
    ctx = "\n\n".join(retrieve(question))
    prompt = f"仅根据下面的资料回答问题,资料里没有就回答'不知道'。\n\n资料:\n{ctx}\n\n问题:{question}"
    return chat(prompt, max_tokens=800)

print(rag_answer("退货政策是怎样的?"))

几个让检索更准的小习惯:分块带重叠,避免切断语义;top_k 取 3~5 段;最相关的放最前面;提示模型只依据资料,减少编造。

6. 多智能体模式(Agents)

单次 Claude 调用能做的事有限。把多次调用按套路编排起来,才谈得上"Agent 系统"。三个最实用的模式:

6.1 基础工作流:路由 + 顺序 + 循环

用模型当路由器,判断该走哪条分支,再顺序或循环执行。

python 复制代码
def router(user_msg):
    """判断用户意图,返回分支名。"""
    decision = chat(
        "用户这句话属于哪类?只回一个词:sales / support / other。\n" + user_msg,
        max_tokens=20
    ).strip().lower()
    return decision

def handle(user_msg):
    branch = router(user_msg)
    if branch == "sales":
        return chat("你是销售助手,回答:" + user_msg)
    if branch == "support":
        return chat("你是客服助手,回答:" + user_msg)
    return chat("通用回答:" + user_msg)

# 循环:反复处理,直到模型说"完成"
def loop_until_done(task, max_iter=5):
    msgs = [{"role": "user", "content": task}]
    for _ in range(max_iter):
        r = client.messages.create(model=MODEL, max_tokens=1024, messages=msgs)
        text = r.content[0].text
        msgs.append({"role": "assistant", "content": text})
        if "完成" in text:
            return text
        msgs.append({"role": "user", "content": "继续,直到任务结束再说'完成'。"})
    return msgs[-1]["content"]

6.2 编排器-工作者(Orchestrator-Workers)

主 Agent 把大任务拆成子任务,分发给多个工作者并行处理,最后汇总。调研、代码生成、长文写作都适合这套。

python 复制代码
def orchestrate(big_task):
    # 1) 编排器拆解任务
    plan = chat(f"把下面这个任务拆成 3-5 个独立子任务,每行一个:\n{big_task}", max_tokens=500)
    subtasks = [t for t in plan.splitlines() if t.strip()]

    # 2) 工作者并行执行(真实可用 concurrent.futures 并发)
    results = []
    for st in subtasks:
        results.append(chat(f"请完成这个子任务并给出结果:\n{st}", max_tokens=800))

    # 3) 汇总
    joined = "\n\n".join(f"子任务{i+1}: {r}" for i, r in enumerate(results))
    return chat(f"根据下列子任务结果,整合成最终交付物:\n{joined}", max_tokens=1000)

print(orchestrate("写一份'AI 客服系统'的技术方案,含架构、技术栈、排期。"))

6.3 评估-优化(Evaluator-Optimizer)

一个生成器出结果,一个评估器打分、给修改建议,生成器照着改,直到通过。写代码、写文案、做翻译都用得上。

python 复制代码
def generate(task, feedback=""):
    extra = f"\n\n评审反馈(请据此改进):{feedback}" if feedback else ""
    return chat(f"完成任务:{task}{extra}", max_tokens=1000)

def evaluate(task, draft):
    return chat(
        f"请评审下面的成果是否达成任务要求,给出'通过/不通过'和具体改进点。\n"
        f"任务:{task}\n成果:{draft}", max_tokens=400)

def improve(task, rounds=3):
    draft = generate(task)
    for _ in range(rounds):
        review = evaluate(task, draft)
        if review.strip().startswith("通过"):
            return draft, review
        draft = generate(task, feedback=review)
    return draft, "已达轮次上限"

final, note = improve("写一段产品发布会开场白,热情、简洁、不超过 80 字。")
print(final, "\n---评审---", note)

怎么选:能一次做对就直接调;要分流用路由;任务大而能拆用编排器-工作者;质量要反复打磨用评估-优化。它们也能组合起来用。

7. 其他能力速查

能力 核心做法 关键代码片段
文本摘要 长文分段摘要再聚合;用 max_tokens 控制粒度 chat(f"用3句话总结:{text}")
文本分类 few-shot 加限定标签;用 tool_choice 强制结构化输出 tool_choice={"type":"tool","name":"classify"}
Text-to-SQL 把数据库 Schema 放进 prompt,让模型生成 SQL 再由你执行 见下
知识图谱 抽取实体/关系,存图库(如 Neo4j),再图查询 见下
python 复制代码
# Text-to-SQL:把建表语句喂给模型,让它生成可执行的 SQL
SCHEMA = """
CREATE TABLE orders(id INT, user_id INT, amount DECIMAL, created_at DATE);
CREATE TABLE users(id INT, name TEXT, city TEXT);
"""
sql = chat(
    f"数据库 Schema:\n{SCHEMA}\n请只生成一条 SQL 回答:'北京用户的总消费是多少?'",
    max_tokens=300
).strip()
# 拿到 sql 后,用你的数据库驱动(sqlite3 / psycopg2)执行,不要把模型输出直接当命令跑

# 知识图谱抽取(最小骨架)
kg_triples = chat(
    "从下面文本抽取 (实体, 关系, 实体) 三元组,每行一个:\n" + text,
    max_tokens=500
)

模型生成的 SQL 或命令,永远别直接执行。至少做白名单校验、只读权限、参数化查询,最好人工复核一遍。

8. 上下文工程(Context Engineering)

最近圈子里总提"上下文工程",听着玄,说的事其实挺朴素:别再往系统提示里堆一大堆死规则,而是把对的事例、对工具、对的历史,在需要的时候动态塞进上下文,剩下的交给模型的判断力。

我自己踩下来,体感是这样的:

系统提示能短就短。细节留给工具描述和 few-shot 示例,比写一堆"如果......就......"管用。

历史要会扔。长对话按 2.5 节那样压一压,不相关的干脆删掉,别舍不得。

记忆和知识按需取。别一上来把全部资料怼进 prompt,用到再检索。

敢信模型。把目标和安全边界说清就行,别用几十条规则把它捆死。

回过头看,前面写的记忆压缩、RAG 检索、工具选择,干的其实都是同一件事:把对的上下文在对的时机喂进去。把它们当工具箱用,别当教条。

总结

到这儿,你已经能用 Claude API 搭出一个会查资料、会算账、能看图、还能多步推理的 Agent 了。剩下的事不复杂:把示例里的模拟函数,换成你自己的真实业务逻辑就行。

想继续往下挖,这几个地方值得看:

觉得有用就点个赞,或者收藏起来下次照着敲。哪一块想让我展开讲(比如完整的 RAG 工程、Agent 并发框架),评论区说一声,下篇可以安排。

相关推荐
秦先生在广东1 小时前
`claude-video /watch`:给 Claude 装上“眼睛“看视频的工程实现与边界分析
人工智能
极客猴子1 小时前
会议记录APP怎么选 2026年实测功能对比与使用指南
人工智能·xcode
秦先生在广东1 小时前
Impeccable:给 AI 编码 Agent 装上设计判断力的工具包
人工智能
hnsoyon1 小时前
智慧城市方案强调预防供水在线监测系统预警水质异常
人工智能·智慧城市·智慧城市方案·供水在线监测系统
Nontee221 小时前
开源 AI 模型到底该不该禁?Anthropic 的一场"不情愿的澄清",撕开了硅谷最深的裂痕
人工智能
无敌秋2 小时前
无线接入网 RAN
人工智能
小林AI Flow2 小时前
数据标注遇到边界样本怎么办?先写规则再做一致性检查
人工智能·数据标注·人工智能训练师·ai训练师
景同学2 小时前
把 AI 用到线上运维:可行、有效,前提是喂足信息——一次 Full GC 排障实录
java·人工智能·后端
触底反弹2 小时前
🔥 从 MySQL 到 Milvus:用 AI 日记本项目搞懂向量数据库和 RAG
javascript·人工智能·面试