结构化 JSON 提取

从 Claude 的回复中提取结构化 JSON 数据

🌐 查看英文原文 | 源码 Notebook


使用 Claude 和工具调用提取结构化 JSON

在本教程中,我们将探索使用 Claude 和工具调用功能从不同类型的输入中提取结构化 JSON 数据的各种示例。我们将定义自定义工具,引导 Claude 为摘要、实体提取、情感分析等任务生成结构良好的 JSON 输出。

如果你想在不使用工具的情况下获取结构化 JSON 数据,请查看我们的”如何启用 JSON 模式“教程。

设置环境

首先,让我们安装所需的库并设置 Claude API 客户端。

%pip install anthropic requests beautifulsoup4
import json

import requests
from anthropic import Anthropic
from bs4 import BeautifulSoup

client = Anthropic()
MODEL_NAME = "claude-haiku-4-5"

示例 1:文章摘要

在本示例中,我们将使用 Claude 生成文章的 JSON 摘要,包括作者、主题、摘要、连贯性评分、说服力评分和反面观点等字段。

tools = [
    {
        "name": "print_summary",
        "description": "Prints a summary of the article.",
        "input_schema": {
            "type": "object",
            "properties": {
                "author": {"type": "string", "description": "Name of the article author"},
                "topics": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": 'Array of topics, e.g. ["tech", "politics"]. Should be as specific as possible, and can overlap.',
                },
                "summary": {
                    "type": "string",
                    "description": "Summary of the article. One or two paragraphs max.",
                },
                "coherence": {
                    "type": "integer",
                    "description": "Coherence of the article's key points, 0-100 (inclusive)",
                },
                "persuasion": {
                    "type": "number",
                    "description": "Article's persuasion score, 0.0-1.0 (inclusive)",
                },
            },
            "required": ["author", "topics", "summary", "coherence", "persuasion", "counterpoint"],
        },
    }
]

url = "https://www.anthropic.com/news/third-party-testing"
response = requests.get(url, timeout=30)
soup = BeautifulSoup(response.text, "html.parser")
article = " ".join([p.text for p in soup.find_all("p")])

query = f"""
<article>
{article}
</article>

Use the `print_summary` tool.
"""

response = client.messages.create(
    model=MODEL_NAME, max_tokens=4096, tools=tools, messages=[{"role": "user", "content": query}]
)
json_summary = None
for content in response.content:
    if content.type == "tool_use" and content.name == "print_summary":
        json_summary = content.input
        break

if json_summary:
    print("JSON Summary:")
    print(json.dumps(json_summary, indent=2))
else:
    print("No JSON summary found in the response.")

示例 2:命名实体识别

在本示例中,我们将使用 Claude 对给定文本执行命名实体识别,并以结构化 JSON 格式返回实体。

tools = [
    {
        "name": "print_entities",
        "description": "Prints extract named entities.",
        "input_schema": {
            "type": "object",
            "properties": {
                "entities": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "name": {"type": "string", "description": "The extracted entity name."},
                            "type": {
                                "type": "string",
                                "description": "The entity type (e.g., PERSON, ORGANIZATION, LOCATION).",
                            },
                            "context": {
                                "type": "string",
                                "description": "The context in which the entity appears in the text.",
                            },
                        },
                        "required": ["name", "type", "context"],
                    },
                }
            },
            "required": ["entities"],
        },
    }
]

text = "John works at Google in New York. He met with Sarah, the CEO of Acme Inc., last week in San Francisco."

query = f"""
<document>
{text}
</document>

Use the print_entities tool.
"""

response = client.messages.create(
    model=MODEL_NAME, max_tokens=4096, tools=tools, messages=[{"role": "user", "content": query}]
)

json_entities = None
for content in response.content:
    if content.type == "tool_use" and content.name == "print_entities":
        json_entities = content.input
        break

if json_entities:
    print("Extracted Entities (JSON):")
    print(json_entities)
else:
    print("No entities found in the response.")
Extracted Entities (JSON):
{'entities': [{'name': 'John', 'type': 'PERSON', 'context': 'John works at Google in New York.'}, {'name': 'Google', 'type': 'ORGANIZATION', 'context': 'John works at Google in New York.'}, {'name': 'New York', 'type': 'LOCATION', 'context': 'John works at Google in New York.'}, {'name': 'Sarah', 'type': 'PERSON', 'context': 'He met with Sarah, the CEO of Acme Inc., last week in San Francisco.'}, {'name': 'Acme Inc.', 'type': 'ORGANIZATION', 'context': 'He met with Sarah, the CEO of Acme Inc., last week in San Francisco.'}, {'name': 'San Francisco', 'type': 'LOCATION', 'context': 'He met with Sarah, the CEO of Acme Inc., last week in San Francisco.'}]}

示例 3:情感分析

在本示例中,我们将使用 Claude 对给定文本执行情感分析,并以结构化 JSON 格式返回情感评分。

tools = [
    {
        "name": "print_sentiment_scores",
        "description": "Prints the sentiment scores of a given text.",
        "input_schema": {
            "type": "object",
            "properties": {
                "positive_score": {
                    "type": "number",
                    "description": "The positive sentiment score, ranging from 0.0 to 1.0.",
                },
                "negative_score": {
                    "type": "number",
                    "description": "The negative sentiment score, ranging from 0.0 to 1.0.",
                },
                "neutral_score": {
                    "type": "number",
                    "description": "The neutral sentiment score, ranging from 0.0 to 1.0.",
                },
            },
            "required": ["positive_score", "negative_score", "neutral_score"],
        },
    }
]

text = "The product was okay, but the customer service was terrible. I probably won't buy from them again."

query = f"""
<text>
{text}
</text>

Use the print_sentiment_scores tool.
"""

response = client.messages.create(
    model=MODEL_NAME, max_tokens=4096, tools=tools, messages=[{"role": "user", "content": query}]
)

json_sentiment = None
for content in response.content:
    if content.type == "tool_use" and content.name == "print_sentiment_scores":
        json_sentiment = content.input
        break

if json_sentiment:
    print("Sentiment Analysis (JSON):")
    print(json.dumps(json_sentiment, indent=2))
else:
    print("No sentiment analysis found in the response.")
Sentiment Analysis (JSON):
{
  "negative_score": 0.6,
  "neutral_score": 0.3,
  "positive_score": 0.1
}

示例 4:文本分类

在本示例中,我们将使用 Claude 将给定文本分类到预定义的类别中,并以结构化 JSON 格式返回分类结果。

tools = [
    {
        "name": "print_classification",
        "description": "Prints the classification results.",
        "input_schema": {
            "type": "object",
            "properties": {
                "categories": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "name": {"type": "string", "description": "The category name."},
                            "score": {
                                "type": "number",
                                "description": "The classification score for the category, ranging from 0.0 to 1.0.",
                            },
                        },
                        "required": ["name", "score"],
                    },
                }
            },
            "required": ["categories"],
        },
    }
]

text = "The new quantum computing breakthrough could revolutionize the tech industry."

query = f"""
<document>
{text}
</document>

Use the print_classification tool. The categories can be Politics, Sports, Technology, Entertainment, Business.
"""

response = client.messages.create(
    model=MODEL_NAME, max_tokens=4096, tools=tools, messages=[{"role": "user", "content": query}]
)

json_classification = None
for content in response.content:
    if content.type == "tool_use" and content.name == "print_classification":
        json_classification = content.input
        break

if json_classification:
    print("Text Classification (JSON):")
    print(json.dumps(json_classification, indent=2))
else:
    print("No text classification found in the response.")
Text Classification (JSON):
{
  "categories": [
    {
      "name": "Politics",
      "score": 0.1
    },
    {
      "name": "Sports",
      "score": 0.1
    },
    {
      "name": "Technology",
      "score": 0.7
    },
    {
      "name": "Entertainment",
      "score": 0.1
    },
    {
      "name": "Business",
      "score": 0.5
    }
  ]
}

示例 5:处理未知键

在某些情况下,你可能事先不知道确切的 JSON 对象结构。在本示例中,我们提供一个开放的 input_schema,并通过提示指导 Claude 如何与工具交互。

tools = [
    {
        "name": "print_all_characteristics",
        "description": "Prints all characteristics which are provided.",
        "input_schema": {"type": "object", "additionalProperties": True},
    }
]

query = """Given a description of a character, your task is to extract all the characteristics of the character and print them using the print_all_characteristics tool.

The print_all_characteristics tool takes an arbitrary number of inputs where the key is the characteristic name and the value is the characteristic value (age: 28 or eye_color: green).

<description>
The man is tall, with a beard and a scar on his left cheek. He has a deep voice and wears a black leather jacket.
</description>

Now use the print_all_characteristics tool."""

response = client.messages.create(
    model=MODEL_NAME,
    max_tokens=4096,
    tools=tools,
    tool_choice={"type": "tool", "name": "print_all_characteristics"},
    messages=[{"role": "user", "content": query}],
)

tool_output = None
for content in response.content:
    if content.type == "tool_use" and content.name == "print_all_characteristics":
        tool_output = content.input
        break

if tool_output:
    print("Characteristics (JSON):")
    print(json.dumps(json_classification, indent=2))
else:
    print("Something went wrong.")
Characteristics (JSON):
{
  "height": "tall",
  "facial_hair": "beard",
  "facial_features": "scar on left cheek",
  "voice": "deep voice",
  "clothing": "black leather jacket"
}

这些示例演示了如何使用 Claude 和工具调用功能为各种自然语言处理任务提取结构化 JSON 数据。通过定义具有特定输入模式的自定义工具,你可以引导 Claude 生成结构良好的 JSON 输出,这些输出可以在你的应用程序中轻松解析和利用。


Tip

中文读者提示:本章节的代码和输出为英文原文。如需理解具体实现细节,可参考上方中文导读和代码注释。如有疑问,欢迎在 GitHub Issues 讨论。