24
24
samWeatherTool = schema .NewTool ("get_weather" , "Get the weather for a location" )
25
25
samNewsHeadlinesTool = schema .NewTool ("get_news_headlines" , "Get the news headlines" )
26
26
samNewsSearchTool = schema .NewTool ("search_news" , "Search news articles" )
27
- samSystemPrompt = `Your name is Samantha, you are a friendly AI assistant, here to help you with
28
- anything you need. Your responses should be short and to the point, and you should always be polite.`
27
+ samHomeAssistantTool = schema .NewTool ("get_home_devices" , "Return information about home devices" )
28
+ samSystemPrompt = `Your name is Samantha, you are a friendly and occasionally sarcastic assistant,
29
+ here to help with anything. Your responses should be short and to the point, and you should always be polite.`
29
30
)
30
31
31
32
///////////////////////////////////////////////////////////////////////////////
@@ -51,23 +52,32 @@ func samParse(flags *Flags, opts ...client.ClientOpt) error {
51
52
if err := newsapiParse (flags , opts ... ); err != nil {
52
53
return err
53
54
}
54
-
55
+ // Initialize home assistant
56
+ if err := haParse (flags , opts ... ); err != nil {
57
+ return err
58
+ }
55
59
// Initialize anthropic
56
60
opts = append (opts , client .OptHeader ("Anthropic-Beta" , "tools-2024-04-04" ))
57
61
if err := anthropicParse (flags , opts ... ); err != nil {
58
62
return err
59
63
}
60
64
61
65
// Add tool parameters
62
- if err := samWeatherTool .AddParameter ("location" , "The city to get the weather for" , true ); err != nil {
66
+ if err := samWeatherTool .AddParameter ("location" , `City to get the weather for. If a country, use the capital city. To get weather for the current location, use "auto:ip"` , true ); err != nil {
63
67
return err
64
68
}
65
69
if err := samNewsHeadlinesTool .AddParameter ("category" , "The cateogry of news, which should be one of business, entertainment, general, health, science, sports or technology" , true ); err != nil {
66
70
return err
67
71
}
72
+ if err := samNewsHeadlinesTool .AddParameter ("country" , "Headlines from agencies in a specific country. Optional. Use ISO 3166 country code." , false ); err != nil {
73
+ return err
74
+ }
68
75
if err := samNewsSearchTool .AddParameter ("query" , "The query with which to search news" , true ); err != nil {
69
76
return err
70
77
}
78
+ if err := samHomeAssistantTool .AddParameter ("class" , "The class of device, which should be one or more of door,lock,occupancy,motion,climate,light,switch,sensor,speaker,media_player,temperature,humidity,battery,tv,remote,light,vacuum separated by spaces" , true ); err != nil {
79
+ return err
80
+ }
71
81
72
82
// Return success
73
83
return nil
@@ -99,18 +109,32 @@ func samChat(ctx context.Context, w *tablewriter.Writer, _ []string) error {
99
109
// Curtail requests to the last N history
100
110
if len (messages ) > 10 {
101
111
messages = messages [len (messages )- 10 :]
102
- // First message must have role 'user'
112
+
113
+ // First message must have role 'user' and not be a tool_result
103
114
for {
104
- if len (messages ) == 0 || messages [ 0 ]. Role == "user" {
115
+ if len (messages ) == 0 {
105
116
break
106
117
}
118
+ if messages [0 ].Role == "user" {
119
+ if content , ok := messages [0 ].Content .([]schema.Content ); ok {
120
+ if len (content ) > 0 && content [0 ].Type != "tool_result" {
121
+ break
122
+ }
123
+ } else {
124
+ break
125
+ }
126
+ }
107
127
messages = messages [1 :]
108
128
}
109
- // TODO: We must remove the first instance tool_result if there is no tool_use
110
129
}
111
130
112
131
// Request -> Response
113
- responses , err := anthropicClient .Messages (ctx , messages , anthropic .OptSystem (samSystemPrompt ), anthropic .OptTool (samWeatherTool ), anthropic .OptTool (samNewsHeadlinesTool ), anthropic .OptTool (samNewsSearchTool ))
132
+ responses , err := anthropicClient .Messages (ctx , messages , anthropic .OptSystem (samSystemPrompt ),
133
+ anthropic .OptTool (samWeatherTool ),
134
+ anthropic .OptTool (samNewsHeadlinesTool ),
135
+ anthropic .OptTool (samNewsSearchTool ),
136
+ anthropic .OptTool (samHomeAssistantTool ),
137
+ )
114
138
if err != nil {
115
139
return err
116
140
}
@@ -158,7 +182,8 @@ func samCall(_ context.Context, content schema.Content) *schema.Content {
158
182
} else {
159
183
category = "general"
160
184
}
161
- if headlines , err := newsapiClient .Headlines (newsapi .OptCategory (category )); err != nil {
185
+ country , _ := content .GetString (content .Name , "country" )
186
+ if headlines , err := newsapiClient .Headlines (newsapi .OptCategory (category ), newsapi .OptCountry (country )); err != nil {
162
187
return schema .ToolResult (content .Id , fmt .Sprint ("Unable to get the news headlines, the error is " , err ))
163
188
} else if data , err := json .MarshalIndent (headlines , "" , " " ); err != nil {
164
189
return schema .ToolResult (content .Id , fmt .Sprint ("Unable to marshal the headlines data, the error is " , err ))
@@ -179,6 +204,18 @@ func samCall(_ context.Context, content schema.Content) *schema.Content {
179
204
} else {
180
205
return schema .ToolResult (content .Id , string (data ))
181
206
}
207
+ case samHomeAssistantTool .Name :
208
+ classes , exists := content .GetString (content .Name , "class" )
209
+ if ! exists || classes == "" {
210
+ return schema .ToolResult (content .Id , "Unable to get home devices due to missing class" )
211
+ }
212
+ if states , err := haGetStates (strings .Fields (classes )); err != nil {
213
+ return schema .ToolResult (content .Id , fmt .Sprint ("Unable to get home devices, the error is " , err ))
214
+ } else if data , err := json .MarshalIndent (states , "" , " " ); err != nil {
215
+ return schema .ToolResult (content .Id , fmt .Sprint ("Unable to marshal the states data, the error is " , err ))
216
+ } else {
217
+ return schema .ToolResult (content .Id , string (data ))
218
+ }
182
219
}
183
220
return schema .ToolResult (content .Id , fmt .Sprint ("unable to call:" , content .Name ))
184
221
}
0 commit comments