5
5
// Created by Fumito Ito on 2024/03/17.
6
6
//
7
7
8
- // swiftlint:disable file_length
9
-
10
8
import Foundation
11
9
import FunctionCalling
12
10
13
- // swiftlint:disable:next type_body_length
14
11
public struct Messages {
15
12
private let apiKey : String
16
13
private let session : URLSession
@@ -46,7 +43,7 @@ public struct Messages {
46
43
temperature: Double ? = nil ,
47
44
topP: Double ? = nil ,
48
45
topK: Int ? = nil ,
49
- toolContainer : ToolContainer ? = nil ,
46
+ tools : [ Tool ] ? = nil ,
50
47
toolChoice: ToolChoice = . auto
51
48
) async throws -> MessagesResponse {
52
49
try await createMessage (
@@ -59,7 +56,7 @@ public struct Messages {
59
56
temperature: temperature,
60
57
topP: topP,
61
58
topK: topK,
62
- toolContainer : toolContainer ,
59
+ tools : tools ,
63
60
toolChoice: toolChoice,
64
61
anthropicHeaderProvider: DefaultAnthropicHeaderProvider ( ) ,
65
62
authenticationHeaderProvider: APIKeyAuthenticationHeaderProvider ( apiKey: apiKey)
@@ -94,7 +91,7 @@ public struct Messages {
94
91
temperature: Double ? = nil ,
95
92
topP: Double ? = nil ,
96
93
topK: Int ? = nil ,
97
- toolContainer : ToolContainer ? = nil ,
94
+ tools : [ Tool ] ? = nil ,
98
95
toolChoice: ToolChoice = . auto,
99
96
anthropicHeaderProvider: AnthropicHeaderProvider ,
100
97
authenticationHeaderProvider: AuthenticationHeaderProvider
@@ -117,7 +114,7 @@ public struct Messages {
117
114
temperature: temperature,
118
115
topP: topP,
119
116
topK: topK,
120
- tools: toolContainer ? . allTools ,
117
+ tools: tools ,
121
118
toolChoice: toolChoice
122
119
)
123
120
)
@@ -132,95 +129,7 @@ public struct Messages {
132
129
throw AnthropicAPIError ( fromHttpStatusCode: httpResponse. statusCode)
133
130
}
134
131
135
- let result = try anthropicJSONDecoder. decode ( MessagesResponse . self, from: data)
136
-
137
- guard case . toolUse = result. stopReason else {
138
- return result
139
- }
140
-
141
- return try await sendToolResult (
142
- forToolUseRequest: result,
143
- priviousMessages: messages,
144
- model: model,
145
- system: system,
146
- maxTokens: maxTokens,
147
- metaData: metaData,
148
- stopSequence: stopSequence,
149
- temperature: temperature,
150
- topP: topP,
151
- topK: topK,
152
- toolContainer: toolContainer,
153
- toolChoice: toolChoice,
154
- anthropicHeaderProvider: anthropicHeaderProvider,
155
- authenticationHeaderProvider: authenticationHeaderProvider
156
- )
157
- }
158
-
159
- /// Return the result of tool execution back to the model as a user message
160
- ///
161
- /// - Parameters:
162
- /// - toolUseRequest: Message response from API to execute tools with arguments.
163
- /// - messages: An array of Message objects representing the input prompt for message generation.
164
- /// - model: The model to be used for generating the message. Default is `.claude_3_Opus`.
165
- /// - system: The system identifier. Default is `nil`.
166
- /// - maxTokens: The maximum number of tokens in the generated message.
167
- /// - metaData: Additional metadata for the request. Default is `nil`.
168
- /// - stopSequence: An array of strings representing sequences where the message generation should stop.
169
- /// - temperature: The temperature parameter controls the randomness of the generated text. Default is `nil`.
170
- /// - topP: The nucleus sampling parameter. Default is `nil`.
171
- /// - topK: The top-k sampling parameter. Default is `nil`.
172
- /// - toolContainer: The tool provider for `tool_use`. Default is `nil`
173
- /// - toolChoice: The parameter for tool choice. Default is `.auto`
174
- /// - anthropicHeaderProvider: The provider for the anthropic header NOT required for API authentication.
175
- /// - authenticationHeaderProvider: The provider for the authentication header required for API authentication.
176
- /// - Returns: A `MessagesResponse` object representing the response from the Anthropic API.
177
- /// - Throws: An error if the request fails or if there's an issue decoding the response.
178
- func sendToolResult(
179
- forToolUseRequest toolUseRequest: MessagesResponse ,
180
- priviousMessages messages: [ Message ] ,
181
- model: Model = . claude_3_Opus,
182
- system: [ SystemPrompt ] = [ ] ,
183
- maxTokens: Int ,
184
- metaData: MetaData ? = nil ,
185
- stopSequence: [ String ] ? = nil ,
186
- temperature: Double ? = nil ,
187
- topP: Double ? = nil ,
188
- topK: Int ? = nil ,
189
- toolContainer: ToolContainer ? = nil ,
190
- toolChoice: ToolChoice = . auto,
191
- anthropicHeaderProvider: AnthropicHeaderProvider ,
192
- authenticationHeaderProvider: AuthenticationHeaderProvider
193
- ) async throws -> MessagesResponse {
194
- // If a `tool_use` response is returned with no `ToolContainer` specified, `tool_use_result` cannot be returned because any tool does not exist.
195
- guard let toolContainer else {
196
- throw ClientError . anyToolsAreDefined
197
- }
198
-
199
- guard case . toolUse( let toolUseContent) = toolUseRequest. content. first ( where: { $0. contentType == . toolUse } ) else {
200
- throw ClientError . cannotFindToolUseContentFromResponse ( toolUseRequest)
201
- }
202
-
203
- let toolResult = await toolContainer. execute ( methodName: toolUseContent. name, parameters: toolUseContent. input)
204
- let toolResultRequest = messages + [
205
- . init( role: . assistant, content: [ . toolUse( toolUseContent) ] ) ,
206
- . init( role: . user, content: [ . toolResult( . init( toolUseId: toolUseContent. id, content: [ . text( toolResult) ] , isError: nil ) ) ] )
207
- ]
208
-
209
- return try await createMessage (
210
- toolResultRequest,
211
- model: model,
212
- system: system,
213
- maxTokens: maxTokens,
214
- metaData: metaData,
215
- stopSequence: stopSequence,
216
- temperature: temperature,
217
- topP: topP,
218
- topK: topK,
219
- toolContainer: toolContainer,
220
- toolChoice: toolChoice,
221
- anthropicHeaderProvider: anthropicHeaderProvider,
222
- authenticationHeaderProvider: authenticationHeaderProvider
223
- )
132
+ return try anthropicJSONDecoder. decode ( MessagesResponse . self, from: data)
224
133
}
225
134
226
135
/// Streams messages using the specified parameters and sends a request to the Anthropic API asynchronously.
@@ -249,7 +158,7 @@ public struct Messages {
249
158
temperature: Double ? = nil ,
250
159
topP: Double ? = nil ,
251
160
topK: Int ? = nil ,
252
- toolContainer : ToolContainer ? = nil ,
161
+ tools : [ Tool ] ? = nil ,
253
162
toolChoice: ToolChoice = . auto
254
163
) async throws -> AsyncThrowingStream < StreamingResponse , Error > {
255
164
try await streamMessage (
@@ -262,7 +171,7 @@ public struct Messages {
262
171
temperature: temperature,
263
172
topP: topP,
264
173
topK: topK,
265
- toolContainer : toolContainer ,
174
+ tools : tools ,
266
175
toolChoice: toolChoice,
267
176
anthropicHeaderProvider: DefaultAnthropicHeaderProvider ( ) ,
268
177
authenticationHeaderProvider: APIKeyAuthenticationHeaderProvider ( apiKey: apiKey)
@@ -297,7 +206,7 @@ public struct Messages {
297
206
temperature: Double ? = nil ,
298
207
topP: Double ? = nil ,
299
208
topK: Int ? = nil ,
300
- toolContainer : ToolContainer ? = nil ,
209
+ tools : [ Tool ] ? = nil ,
301
210
toolChoice: ToolChoice = . auto,
302
211
anthropicHeaderProvider: AnthropicHeaderProvider ,
303
212
authenticationHeaderProvider: AuthenticationHeaderProvider
@@ -320,7 +229,7 @@ public struct Messages {
320
229
temperature: temperature,
321
230
topP: topP,
322
231
topK: topK,
323
- tools: toolContainer ? . allTools ,
232
+ tools: tools ,
324
233
toolChoice: toolChoice
325
234
)
326
235
)
@@ -335,104 +244,6 @@ public struct Messages {
335
244
throw AnthropicAPIError ( fromHttpStatusCode: httpResponse. statusCode)
336
245
}
337
246
338
- return resendStreamMessageIfClaudeRequestsToolUse (
339
- try await AnthropicStreamingParser . parse ( stream: data. lines) . accumulated ( ) ,
340
- messages: messages,
341
- model: model,
342
- system: system,
343
- maxTokens: maxTokens,
344
- metaData: metaData,
345
- stopSequence: stopSequence,
346
- temperature: temperature,
347
- topP: topP,
348
- topK: topK,
349
- toolContainer: toolContainer,
350
- toolChoice: toolChoice,
351
- anthropicHeaderProvider: anthropicHeaderProvider,
352
- authenticationHeaderProvider: authenticationHeaderProvider
353
- )
354
- }
355
-
356
- /// Receive response from Claude in Stream format.
357
- ///
358
- /// If there is a response related to `tool_use`, the information is compiled and streamed.
359
- ///
360
- /// - Parameters:
361
- /// - stream: response stream from Claude Stream API
362
- /// - messages: An array of Message objects representing the input prompt for message generation.
363
- /// - model: The model to be used for generating the message. Default is `.claude_3_Opus`.
364
- /// - system: The system identifier. Default is `nil`.
365
- /// - maxTokens: The maximum number of tokens in the generated message.
366
- /// - metaData: Additional metadata for the request. Default is `nil`.
367
- /// - stopSequence: An array of strings representing sequences where the message generation should stop.
368
- /// - temperature: The temperature parameter controls the randomness of the generated text. Default is `nil`.
369
- /// - topP: The nucleus sampling parameter. Default is `nil`.
370
- /// - topK: The top-k sampling parameter. Default is `nil`.
371
- /// - toolContainer: The tool provider for `tool_use`. Default is `nil`
372
- /// - toolChoice: The parameter for tool choice. Default is `.auto`
373
- /// - anthropicHeaderProvider: The provider for the anthropic header NOT required for API authentication.
374
- /// - authenticationHeaderProvider: The provider for the authentication header required for API authentication.
375
- /// - Returns: Claude Stream API response stream. If `stream` returns `tool_use` content, this method returns re-request new stream.
376
- // swiftlint:disable:next function_parameter_count
377
- func resendStreamMessageIfClaudeRequestsToolUse(
378
- _ stream: AsyncThrowingStream < StreamingResponse , Error > ,
379
- messages: [ Message ] ,
380
- model: Model ,
381
- system: [ SystemPrompt ] = [ ] ,
382
- maxTokens: Int ,
383
- metaData: MetaData ? ,
384
- stopSequence: [ String ] ? ,
385
- temperature: Double ? ,
386
- topP: Double ? ,
387
- topK: Int ? ,
388
- toolContainer: ToolContainer ? ,
389
- toolChoice: ToolChoice ,
390
- anthropicHeaderProvider: AnthropicHeaderProvider ,
391
- authenticationHeaderProvider: AuthenticationHeaderProvider
392
- ) -> AsyncThrowingStream < StreamingResponse , Error > {
393
- AsyncThrowingStream { continuation in
394
- Task {
395
- do {
396
- for try await response in stream {
397
- if
398
- let toolContainer,
399
- let deltaResponse = response as? StreamingMessageDeltaResponse ,
400
- let toolUseContent = deltaResponse. toolUseContent,
401
- let toolResultContent = await deltaResponse. getToolResultContent ( from: toolContainer) ,
402
- response. isToolUse {
403
- let streamWithToolResult = try await streamMessage (
404
- messages + [
405
- . init( role: . assistant, content: [ . toolUse( toolUseContent) ] ) ,
406
- . init( role: . user, content: [ toolResultContent] )
407
- ] ,
408
- model: model,
409
- system: system,
410
- maxTokens: maxTokens,
411
- metaData: metaData,
412
- stopSequence: stopSequence,
413
- temperature: temperature,
414
- topP: topP,
415
- topK: topK,
416
- toolContainer: toolContainer,
417
- toolChoice: toolChoice,
418
- anthropicHeaderProvider: anthropicHeaderProvider,
419
- authenticationHeaderProvider: authenticationHeaderProvider
420
- )
421
-
422
- for try await responseWithToolResult in streamWithToolResult {
423
- continuation. yield ( responseWithToolResult)
424
- }
425
- } else {
426
- continuation. yield ( response)
427
- }
428
- }
429
- continuation. finish ( )
430
- } catch {
431
- continuation. finish ( throwing: error)
432
- }
433
- }
434
- }
247
+ return try await AnthropicStreamingParser . parse ( stream: data. lines) . accumulated ( )
435
248
}
436
249
}
437
-
438
- // swiftlint:enable file_length
0 commit comments