Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for tool use in anthropic_sdk_dart client #469

Merged
merged 1 commit into from
Jun 22, 2024

Conversation

davidmigloz
Copy link
Owner

@davidmigloz davidmigloz commented Jun 22, 2024

Claude is capable of interacting with external client-side tools and functions, allowing you to equip Claude with your own custom tools to perform a wider variety of tasks.

Refer to the official documentation for more information.

In the following example, we want the model to be able to use our function that return the current weather in a given city:

Map<String, dynamic> _getCurrentWeather(
  final String location,
  final String unit,
) {
  const temperature = 22;
  const weather = 'Sunny';
  return {
    'temperature': unit == 'celsius' ? temperature : (temperature * 9 / 5) + 32,
    'unit': unit,
    'description': weather,
  };
}

To do that, we need to provide the definition of the tool:

const tool = Tool(
  name: 'get_current_weather',
  description: 'Get the current weather in a given location',
  inputSchema: {
    'type': 'object',
    'properties': {
      'location': {
        'type': 'string',
        'description': 'The city and state, e.g. San Francisco, CA',
      },
      'unit': {
        'type': 'string',
        'description': 'The unit of temperature to return',
        'enum': ['celsius', 'fahrenheit'],
      },
    },
    'required': ['location'],
  },
);

Then we can use the tool in the message request:

final request1 = CreateMessageRequest(
  model: Model.model(Models.claude35Sonnet20240620),
  messages: [
    Message(
      role: MessageRole.user,
      content: MessageContent.text(
        'What’s the weather like in Boston right now?',
      ),
    ),
  ],
  tools: [tool],
  toolChoice: ToolChoice(
    type: ToolChoiceType.tool,
    name: tool.name,
  ),
  maxTokens: 1024,
);
final aiMessage1 = await client.createMessage(request: request1);

final toolUse = aiMessage1.content.blocks.firstOrNull;
if (toolUse == null || toolUse is! ToolUseBlock) {
  return;
}

// Call your tool here with the given input
final toolResult = _getCurrentWeather(
  toolUse.input['location'],
  toolUse.input['unit'],
);

final request2 = CreateMessageRequest(
  model: Model.model(Models.claude35Sonnet20240620),
  messages: [
    Message(
      role: MessageRole.user,
      content: MessageContent.text(
        'What’s the weather like in Boston right now in Fahrenheit?',
      ),
    ),
    Message(
      role: MessageRole.assistant,
      content: aiMessage1.content,
    ),
    Message(
      role: MessageRole.user,
      content: MessageContent.blocks([
        Block.toolResult(
          toolUseId: toolUse.id,
          content: ToolResultBlockContent.text(json.encode(toolResult)),
        ),
      ]),
    ),
  ],
  tools: [tool],
  maxTokens: 1024,
);
final aiMessage2 = await client.createMessage(request: request2);

print(aiMessage2.content.text);
// Based on the current weather information for Boston, here's what it's like right now:
//
// The temperature in Boston is 71.6°F (Fahrenheit).
// The weather conditions are described as sunny.

You can also stream the input for a tool:

final stream = client.createMessageStream(request: request);
await for (final res in stream) {
  res.map(
    messageStart: (MessageStartEvent v) {},
    messageDelta: (MessageDeltaEvent v) {},
    messageStop: (MessageStopEvent v) {},
    contentBlockStart: (ContentBlockStartEvent v) {},
    contentBlockDelta: (ContentBlockDeltaEvent v) {
      stdout.write(v.delta.inputJson);
    },
    contentBlockStop: (ContentBlockStopEvent v) {},
    ping: (PingEvent v) {},
  );
}
// {"location": "Boston, MA", "unit": "fahrenheit"}

@davidmigloz davidmigloz self-assigned this Jun 22, 2024
@davidmigloz davidmigloz added t:enhancement New feature or request p:anthropic_sdk_dart anthropic_sdk_dart package. labels Jun 22, 2024
@davidmigloz davidmigloz added this to the v0.8.0 milestone Jun 22, 2024
@davidmigloz davidmigloz merged commit 9edbb02 into main Jun 22, 2024
1 check passed
@davidmigloz davidmigloz deleted the anthropic-tools branch June 22, 2024 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p:anthropic_sdk_dart anthropic_sdk_dart package. t:enhancement New feature or request
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

1 participant