Skip to content

Commit ff3fe6c

Browse files
authored
Merge pull request #1 from lazy-hq/tool-docs
Tool docs
2 parents 8f3959a + 13a1218 commit ff3fe6c

File tree

2 files changed

+151
-3
lines changed

2 files changed

+151
-3
lines changed

apps/docs/content/docs/concepts/tools.mdx

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,152 @@
22
title: Tools
33
---
44

5-
//TODO:
5+
A 'Tool' is a general term for a function or logic that can be executed by an AI
6+
model. They can be user defined or pre-defined by the provider. Tools are provided
7+
to the AI model's context as per the developer's needs.The AI model can then use the
8+
provided tools to perform specific queries to aid in text generation or actions to
9+
be taken externally. Most common tools include the following searching the web,
10+
querying a public API, executing a shell command, and more.
11+
12+
Here is the recommended and less verbose way to define a tool. It allows you to annotate native
13+
Rust functions with the `#[tool]` macro, which will generate a `Tool` struct for you.
14+
15+
```rust
16+
use crate::core::{tool, Tool};
17+
18+
#[tool]
19+
/// Get the weather information given a location
20+
pub fn get_weather(location: String) {
21+
let weather = match location.as_str() {
22+
// Some logic to query a weather API
23+
"New York" => 75,
24+
"Tokyo" => 80,
25+
_ => 70,
26+
};
27+
Ok(weather.to_string())
28+
}
29+
```
30+
31+
A tool has 4 components:
32+
33+
- **name**: It is used to identify the tool in the AI model. Make sure it is unique and describes
34+
what the tool does well. The name of the tool in this case is `get_weather`.
35+
36+
- **description**: This is a brief description of what the tool does. It is used to
37+
help the AI model understand what the tool does and how to use it. The function's doc comment
38+
as the description. you can use rust style documentation with examples for few-shot prompting
39+
40+
- **arguments**: This is the schema of the input that the AI model will use to generate
41+
inputs for the tool. It uses the [schemars](https://docs.rs/schemars/latest/schemars/) crate
42+
to define the [json schema](https://json-schema.org/) of the input. The function's arguments
43+
are serialized into json schema in which the AI model will use to generate inputs.
44+
just make sure
45+
the arguments implement the `schemars::JsonSchema` trait or are natively supported
46+
by the `schemars` crate.
47+
48+
- **body**: This is the logic that will be called when the AI model calls the tool. it
49+
takes a single argument of type `serde_json::Value` which is the json input provided by the AI model. the function should return a `Result<String, String>`
50+
which is the output of the tool. If the tool fails, you can return an error message as `Err(String)` which can
51+
also be helpful for the AI model to understand what went wrong.
52+
53+
You can optionally override the `name` and `description` of the tool by passing them as arguments to the `#[tool]` macro.
54+
55+
```rust
56+
use crate::core::{tool, Tool};
57+
58+
#[tool(name = "get-weather", description = "Get the weather information given a location")]
59+
/// A tool that returns the weather information given a location
60+
pub fn get_weather(location: String) {
61+
let weather = match location.as_str() {
62+
// Some logic to query a weather API
63+
"New York" => 75,
64+
"Tokyo" => 80,
65+
_ => 70,
66+
};
67+
Ok(weather.to_string())
68+
}
69+
```
70+
71+
This will make the tool name and description configurable. name will be `get-weather` and description will be `Get the weather information given a location`.
72+
73+
74+
## Using the structs
75+
76+
You can define your own tools in aisdk by instantiating the `Tool` and related structs and passing
77+
it to one of the AI model text generation builders.
78+
79+
```rust
80+
use super::{Tool, ToolExecute};
81+
use serde_json::Value;
82+
83+
// define tool function body, should return Result<String, String>
84+
#[allow(unused_variables)]
85+
let func = ToolExecute::new(Box::new(|inp: Value| {
86+
// Ai SDK will pass in a json object with the following structure
87+
// ```json
88+
// {
89+
// "location": "New York"
90+
// }
91+
// ```
92+
let location = inp.get("location").unwrap();
93+
Ok(format!("Cloudy"))
94+
}));
95+
96+
// define tool input structure
97+
#[derive(schemars::JsonSchema, Debug)]
98+
#[allow(dead_code)]
99+
struct ToolInput {
100+
location: String,
101+
}
102+
103+
// change tool arguments to json schema
104+
// Which will be similar to the following
105+
// ```json
106+
// "properties": {
107+
// "location": {
108+
// "type": "string"
109+
// }
110+
// }
111+
let schema = schemars::schema_for!(ToolInput);
112+
113+
// bring it all together
114+
let get_weather_tool = Tool::builder()
115+
.name("get-weather")
116+
.description("Get the weather information given a location")
117+
.input_schema(schema.clone())
118+
.execute(func)
119+
.build()
120+
.unwrap();
121+
122+
```
123+
124+
## Registering the tool
125+
126+
To register the tool with the AI model, you need to add it to text generation builders using the `with_tool` method. This
127+
appends the tool to the list of tools that the AI model will use to generate text.
128+
129+
```rust
130+
// call the model with the `#[tool]` macro
131+
let result = LanguageModelRequest::builder()
132+
.model(OpenAI::new("gpt-4o"))
133+
.system("You are a helpful assistant with access to tools.")
134+
.prompt("What is the weather in New York?")
135+
.with_tool(get_weather())
136+
.build()
137+
.generate_text()
138+
.await;
139+
```
140+
141+
or if you are using the structs
142+
143+
```rust
144+
// call the model with `Tool` struct
145+
let result = LanguageModelRequest::builder()
146+
.model(OpenAI::new("gpt-4o"))
147+
.system("You are a helpful assistant with access to tools.")
148+
.prompt("What is the weather in New York?")
149+
.with_tool(get_weather_tool) // you don't need to call it if using structs.
150+
.build()
151+
.generate_text()
152+
.await;
153+
```

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"scripts": {
55
"build": "turbo run build",
66
"dev": "turbo run dev",
7-
"format-and-lint": "biome check .",
8-
"format-and-lint:fix": "biome check . --write",
7+
"format-and-lint": "npx biome check .",
8+
"format-and-lint:fix": "npx biome check . --write",
99
"check-types": "turbo run check-types"
1010
},
1111
"devDependencies": {

0 commit comments

Comments
 (0)