用 Python 调用 Claude:从 system prompt 到 Pydantic 结构化输出

2026-09-22 30 预计阅读时间: 1 分钟
来源: realpython.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

调用 Claude API 并不只是把一段文字发给模型。一个可维护的 Python 集成至少要处理三件事:正确使用 Anthropic SDK、区分系统指令与用户输入,以及把模型返回的文本转换成经过验证的数据结构。

下面通过一个“小测验批改器”串起这些概念,并说明哪些地方最容易出错。

先建立正确的消息模型

一次典型调用包含两类输入:

  • system:定义模型的角色、约束和输出规则。
  • messages:保存用户与助手之间的对话内容。

例如,“你是一名 Python 教师”属于长期行为约束,应放在 system 中;“Pydantic 的作用是什么?”才是本轮用户问题。

这种分离不只是代码风格问题。它能避免业务规则与用户输入混在一起,也方便复用同一套系统提示词处理多次请求。

在 Python 中,核心调用形态如下:

from anthropic import Anthropic

client = Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=300,
    system="你是一名严谨的 Python 教师。",
    messages=[
        {
            "role": "user",
            "content": "请用两句话解释 Pydantic 的主要用途。",
        }
    ],
)

print(response.content[0].text)

Anthropic() 默认可以从 ANTHROPIC_API_KEY 环境变量读取密钥。模型名称可能随账号权限和 API 版本变化,因此生产项目最好把它放进配置,而不是散落在代码中。

可运行示例:让 Claude 返回可验证的测验结果

模型生成 JSON,不代表 JSON 一定满足业务要求。字段可能缺失,数字可能越界,甚至整段响应可能不是合法 JSON。Pydantic 的价值在于把这些问题变成明确的验证错误。

下面是一份可以直接改造的最小项目。

1. 安装依赖

python -m venv .venv
source .venv/bin/activate
python -m pip install anthropic pydantic

export ANTHROPIC_API_KEY="替换为你的_API_Key"
export CLAUDE_MODEL="claude-sonnet-4-5"

Windows PowerShell 可使用:

.venv\Scripts\Activate.ps1
$env:ANTHROPIC_API_KEY="替换为你的_API_Key"
$env:CLAUDE_MODEL="claude-sonnet-4-5"

如果你的账号不支持示例中的模型,请将 CLAUDE_MODEL 换成可用的 Claude 模型标识。

2. 创建 quiz.py

import json
import os
import sys

from anthropic import Anthropic
from pydantic import BaseModel, Field, ValidationError


class QuizResult(BaseModel):
    answer: str = Field(min_length=1)
    confidence: float = Field(ge=0.0, le=1.0)
    concepts: list[str] = Field(min_length=1, max_length=3)


def ask_claude(question: str) -> QuizResult:
    schema = json.dumps(QuizResult.model_json_schema(), ensure_ascii=False)

    system_prompt = f"""你是一名 Python API 教师。
回答用户的技术问题,并且只输出一个 JSON 对象。
不要添加 Markdown 代码围栏、标题或解释性前缀。
输出必须符合以下 JSON Schema:
{schema}
"""

    client = Anthropic()
    response = client.messages.create(
        model=os.getenv("CLAUDE_MODEL", "claude-sonnet-4-5"),
        max_tokens=500,
        temperature=0,
        system=system_prompt,
        messages=[
            {
                "role": "user",
                "content": question,
            }
        ],
    )

    raw_text = "".join(
        block.text
        for block in response.content
        if block.type == "text"
    )

    return QuizResult.model_validate_json(raw_text)


if __name__ == "__main__":
    question = (
        sys.argv[1]
        if len(sys.argv) > 1
        else "在 Claude API 调用中,system prompt 和 user message 有什么区别?"
    )

    try:
        result = ask_claude(question)
        print(result.model_dump_json(indent=2))
    except ValidationError as exc:
        print("模型返回了 JSON,但没有通过结构验证:", file=sys.stderr)
        print(exc, file=sys.stderr)
        raise SystemExit(1)

运行:

python quiz.py
python quiz.py "为什么不能直接信任大模型返回的 JSON?"

输出形态类似:

{
  "answer": "system prompt 定义全局角色和行为约束,而 user message 表示用户在当前轮次提出的具体请求。",
  "confidence": 0.98,
  "concepts": [
    "system prompt",
    "user message",
    "角色分离"
  ]
}

这里的关键不是让模型“看起来像”在输出结构化数据,而是执行 QuizResult.model_validate_json()。只有 JSON 语法、字段类型和取值范围都满足模型定义,程序才会得到 QuizResult 对象。

三个容易答错的检查题

system prompt 应不应该塞进第一条 user message?

技术上可以把说明写进用户文本,但这会混淆职责。稳定的角色、语气、边界和输出规范更适合放在 system 参数中;每轮变化的问题放在 messages 中。

response.content[0].text 永远安全吗?

简单示例中经常这样写,但更稳妥的实现应遍历内容块并只提取文本块。响应未来可能包含不同类型的内容,业务代码不应默认第一个块一定是文本。

有了 Pydantic,模型就一定返回正确答案吗?

不会。Pydantic 验证的是结构与约束,而不是事实正确性。confidence 位于 0 到 1 之间,不代表模型对置信度的判断可靠;answer 是字符串,也不代表答案没有事实错误。

因此需要区分三层质量:

  1. JSON 是否可解析。
  2. 数据是否满足 schema。
  3. 内容是否真实、相关并符合业务规则。

Pydantic主要解决前两层中的结构验证问题,第三层通常还需要规则检查、检索、人工审核或测试样例。

从演示代码走向生产环境

这个示例采用“提示模型输出 JSON,再由 Pydantic 验证”的实践方式。它清晰易懂,但仍要为失败路径做设计:

  • 捕获 API 超时、限流和认证错误。
  • 对验证失败设置有限次数的重试,而不是无限重试。
  • 重试时把验证错误反馈给模型,要求只修正格式。
  • 记录请求 ID、模型名、耗时和验证结果,但不要泄露密钥或敏感提示词。
  • 为提示词和 Pydantic 模型建立版本号,避免升级字段后无法解释旧数据。
  • 对用户输入设置长度限制,并根据数据敏感程度决定是否允许发送给外部模型。

一个实用的上线检查表是:密钥是否来自环境或密钥管理服务,模型名是否可配置,输出是否经过验证,异常是否可观测,重试是否有上限,关键答案是否还有业务层校验。

掌握 Anthropic SDK 的调用只是起点。真正可靠的 Claude 应用,会把 system prompt 当作行为契约,把用户消息当作动态输入,再用 Pydantic 把自然语言输出收束为程序可以安全处理的数据。


相关推荐