记事工具,支持 Pydantic 和 Anthropic 工具使用

在此示例中,我们将创建一个工具来保存带有作者和元数据的笔记,并在调用工具时使用 Pydantic 来验证模型的响应。我们将定义必要的 Pydantic 模型,处理工具调用,并确保模型的响应符合预期的模式。

步骤 1:设置环境

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

%pip install anthropic pydantic 'pydantic[email]'
from anthropic import Anthropic
from pydantic import BaseModel, EmailStr, Field
from typing import Optional

client = Anthropic()
MODEL_NAME = "claude-3-opus-20240229"

步骤 2:定义 Pydantic 模型

我们将定义 Pydantic 模型来表示笔记、作者和模型响应的预期模式。这将允许我们在保存笔记时验证和类型检查模型的响应。

class Author(BaseModel):
    name: str
    email: EmailStr

class Note(BaseModel):
    note: str
    author: Author
    tags: Optional[list[str]] = None
    priority: int = Field(ge=1, le=5, default=3)
    is_public: bool = False

class SaveNoteResponse(BaseModel):
    success: bool
    message: str

步骤 3:定义客户端工具

接下来,我们将定义我们的聊天机器人将用于保存笔记的客户端工具。

tools = [
    {
        "name": "save_note",
        "description": "一个保存带有作者和元数据的笔记的工具。",
        "input_schema": {
            "type": "object",
            "properties": {
                "note": {
                    "type": "string",
                    "description": "要保存的笔记内容。"
                },
                "author": {
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "description": "作者姓名。"
                        },
                        "email": {
                            "type": "string",
                            "format": "email",
                            "description": "作者的电子邮件地址。"
                        }
                    },
                    "required": ["name", "email"]
                },
                "priority": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5,
                    "default": 3,
                    "description": "笔记的优先级级别(1-5)。"
                },
                "is_public": {
                    "type": "boolean",
                    "default": False,
                    "description": "指示笔记是否公开访问。"
                }
            },
            "required": ["note", "author"]
        }
    }
]

步骤 4:实现记事工具

我们将创建一个虚拟的记事保存函数,该函数仅打印出笔记已成功保存。如果您确实希望将此笔记保存在某处,可以实现此函数。

def save_note(note: str, author: dict, priority: int = 3, is_public: bool = False) -> None:
    print("笔记已成功保存!")

步骤 5:处理工具调用并生成响应

我们将创建函数来处理 Claude 进行的工具调用,并生成指示笔记保存成功的响应。

def process_tool_call(tool_name, tool_input):
    if tool_name == "save_note":
        note = Note(
            note=tool_input["note"],
            author=Author(
                name=tool_input["author"]["name"],
                email=tool_input["author"]["email"]
            ),
            priority=tool_input.get("priority", 3),
            is_public=tool_input.get("is_public", False)
        )
        save_note(note.note, note.author.model_dump(), note.priority, note.is_public)
        return SaveNoteResponse(success=True, message="笔记已成功保存!")

def generate_response(save_note_response):
    return f"响应:{save_note_response.message}"

步骤 6:与聊天机器人互动

现在,让我们创建一个函数来与聊天机器人互动。我们将发送用户消息,处理 Claude 进行的工具调用,生成响应,使用 Pydantic 验证模型的响应,然后将最终响应返回给用户。

def chatbot_interaction(user_message):
    print(f"\n{'='*50}\n用户消息:{user_message}\n{'='*50}")

    messages = [
        {"role": "user", "content": user_message}
    ]

    message = client.messages.create(
        model=MODEL_NAME,
        max_tokens=4096,
        tools=tools,
        messages=messages
    )

    print(f"\n初始响应:")
    print(f"停止原因:{message.stop_reason}")
    print(f"内容:{message.content}")

    if message.stop_reason == "tool_use":
        tool_use = next(block for block in message.content if block.type == "tool_use")
        tool_name = tool_use.name
        tool_input = tool_use.input

        print(f"\n使用的工具:{tool_name}")
        print(f"工具输入:{tool_input}")

        save_note_response = process_tool_call(tool_name, tool_input)


        print(f"工具结果:{save_note_response}")

        response = client.messages.create(
            model=MODEL_NAME,
            max_tokens=4096,
            messages=[
                {"role": "user", "content": user_message},
                {"role": "assistant", "content": message.content},
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "tool_result",
                            "tool_use_id": tool_use.id,
                            "content": str(save_note_response),
                        }
                    ],
                },
            ],
            tools=tools,
        )
    else:
        response = message

    final_response = next(
        (block.text for block in response.content if hasattr(block, "text")),
        None,
    )
    print(response.content)
    print(f"\n最终响应:{final_response}")

    return final_response

步骤 7:测试聊天机器人

让我们用一个示例查询来测试我们的聊天机器人以保存笔记。

chatbot_interaction("""
你能保存一个包含以下详细信息的私人笔记吗?
笔记:记住要买牛奶和鸡蛋。
作者:John Doe (johndoe@gmail.com)
优先级:4
""")
==================================================
用户消息:
你能保存一个包含以下详细信息的私人笔记吗?
笔记:记住要买牛奶和鸡蛋。
作者:John Doe (johndoe@gmail.com)
优先级:4

==================================================

初始响应:
停止原因:tool_use
内容:[ContentBlock(text='<thinking>\n这里应该使用的相关工具是 save_note,因为请求是保存带有特定详细信息的笔记。\n\n让我们逐一检查参数:\n\nnote:用户提供了笔记内容:“记住要买牛奶和鸡蛋。”\nauthor:用户提供了作者详细信息:\n{\n  "name": "John Doe",\n  "email": "johndoe@gmail.com"\n}\nis_public:虽然用户没有明确说明,但他们要求的是“私人笔记”,因此我们可以推断 is_public 应为 false。\npriority:用户指定了优先级 4。\n\n所有必需的参数都已提供或可以从请求中合理推断出来。我们有足够的信息来调用 save_note。\n</thinking>', type='text'), ContentBlockToolUse(id='toolu_015iteV2eC1C7aUodbkotfiS', input={'note': 'Remember to buy milk and eggs.', 'author': {'name': 'John Doe', 'email': 'johndoe@gmail.com'}, 'is_public': False, 'priority': 4}, name='save_note', type='tool_use')]

使用的工具:save_note
工具输入:{'note': 'Remember to buy milk and eggs.', 'author': {'name': 'John Doe', 'email': 'johndoe@gmail.com'}, 'is_public': False, 'priority': 4}
笔记已成功保存!
工具结果:success=True message='笔记已成功保存!'
[ContentBlock(text='您的私人笔记已成功保存,详细信息如下:\n\n笔记:记住要买牛奶和鸡蛋。\n作者:John Doe (johndoe@gmail.com)\n优先级:4\n可见性:私人\n\n如果您需要其他帮助,请告诉我!', type='text')]

最终响应:您的私人笔记已成功保存,详细信息如下:

笔记:记住要买牛奶和鸡蛋。 
作者:John Doe (johndoe@gmail.com)
优先级:4
可见性:私人

如果您需要其他帮助,请告诉我!





'您的私人笔记已成功保存,详细信息如下:\n\n笔记:记住要买牛奶和鸡蛋。\n作者:John Doe (johndoe@gmail.com)\n优先级:4\n可见性:私人\n\n如果您需要其他帮助,请告诉我!'

在此示例中,我们创建了一个保存带有作者和元数据的笔记的工具。聊天机器人使用 save_note 工具来保存笔记,并在调用工具时使用 Pydantic 来验证模型的响应。Note、Author 和 SaveNoteResponse 模型确保工具输入和模型的响应符合预期的模式。

通过定义清晰的 Pydantic 模型并使用它们来验证模型的响应,我们在与聊天机器人互动和保存笔记时增加了额外的可靠性和安全性。