Skip to content

Commit 2040347

Browse files
committed
[temp] update example
1 parent 7fb1ddd commit 2040347

File tree

7 files changed

+203
-120
lines changed

7 files changed

+203
-120
lines changed

Example.swiftpm/ContentView.swift

Lines changed: 26 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,13 @@
11
import SwiftUI
2-
import AnthropicSwiftSDK_VertexAI
32
import AnthropicSwiftSDK
4-
import AWSBedrockRuntime
5-
import AnthropicSwiftSDK_Bedrock
63

74
struct ContentView: View {
85
// MARK: Properties for Claude
96
@State private var claudeAPIKey = ""
10-
@State private var isStreamClaude: Bool = false
11-
12-
// MARK: Properties for Bedrock
13-
@State private var bedrockRegion = ""
14-
@State private var isStreamBedrock: Bool = false
15-
16-
// MARK: Properties for Vertex
17-
@State private var vertexProjectID = ""
18-
@State private var vertexAuthToken = ""
19-
@State private var isStreamVertex: Bool = false
207

218
var body: some View {
229
TabView {
23-
// MARK: Claude
10+
// MARK: Claude Messages API
2411
NavigationStack {
2512
VStack {
2613
Spacer()
@@ -29,20 +16,10 @@ struct ContentView: View {
2916
.padding()
3017
.textFieldStyle(.roundedBorder)
3118

32-
Toggle(isOn: $isStreamClaude) {
33-
Text("Enable Stream API")
34-
}
35-
.padding()
36-
3719
NavigationLink {
3820
let claude = Anthropic(apiKey: claudeAPIKey)
39-
if isStreamClaude {
40-
let observable = StreamViewModel(messageHandler: claude.messages, title: "Stream \\w Claude")
41-
StreamView(observable: observable)
42-
} else {
43-
let observable = SendViewModel(messageHandler: claude.messages, title: "Message \\w Claude")
44-
SendView(observable: observable)
45-
}
21+
let observable = SendViewModel(messageHandler: claude.messages, title: "Message \\w Claude")
22+
SendView(observable: observable)
4623
} label: {
4724
Text("Continue")
4825
.frame(maxWidth: .infinity, minHeight: 48)
@@ -59,108 +36,83 @@ struct ContentView: View {
5936

6037
Spacer()
6138
}
62-
.navigationTitle("Claude Demo")
39+
.navigationTitle("Claude Send Message Demo")
6340
}
6441
.tabItem {
6542
Image(systemName: "pencil.and.scribble")
66-
Text("Claude")
43+
Text("Send Message")
6744
}
68-
69-
// MARK: Bedrock
45+
46+
// MARK: Claude Stream Messages API
7047
NavigationStack {
7148
VStack {
7249
Spacer()
7350

74-
TextField("Enter Region Code", text: $bedrockRegion)
51+
TextField("Enter API Key", text: $claudeAPIKey)
7552
.padding()
7653
.textFieldStyle(.roundedBorder)
7754

78-
Toggle(isOn: $isStreamBedrock) {
79-
Text("Enable Stream API")
80-
}
81-
.padding()
82-
8355
NavigationLink {
84-
let bedrockClient = try! BedrockRuntimeClient(region: bedrockRegion)
85-
let claude = bedrockClient.useAnthropic()
86-
if isStreamBedrock {
87-
let observable = StreamViewModel(messageHandler: claude.messages, title: "Stream \\w Bedrock", model: .claude_3_Opus)
88-
StreamView(observable: observable)
89-
} else {
90-
let observable = SendViewModel(messageHandler: claude.messages, title: "Message \\w Bedrock", model: .claude_3_Opus)
91-
SendView(observable: observable)
92-
}
56+
let claude = Anthropic(apiKey: claudeAPIKey)
57+
let observable = StreamViewModel(messageHandler: claude.messages, title: "Stream \\w Claude")
58+
StreamView(observable: observable)
9359
} label: {
9460
Text("Continue")
9561
.frame(maxWidth: .infinity, minHeight: 48)
9662
.foregroundColor(.white)
9763
.background(
9864
Capsule()
9965
.foregroundColor(
100-
bedrockRegion.isEmpty ? .gray.opacity(0.2) : .blue
66+
claudeAPIKey.isEmpty ? .gray.opacity(0.2) : .blue
10167
)
10268
)
10369
}
10470
.padding()
105-
.disabled(bedrockRegion.isEmpty)
71+
.disabled(claudeAPIKey.isEmpty)
10672

10773
Spacer()
10874
}
109-
.navigationTitle("Bedrock Demo")
75+
.navigationTitle("Claude Stream Message Demo")
11076
}
11177
.tabItem {
112-
Image(systemName: "globe.americas.fill")
113-
Text("Bedrock")
78+
Image(systemName: "pencil.and.scribble")
79+
Text("Stream Message")
11480
}
11581

116-
// MARK: Vertex
82+
// MARK: Claude Send Message Batches API
11783
NavigationStack {
11884
VStack {
11985
Spacer()
12086

121-
TextField("Enter Project ID", text: $vertexProjectID)
122-
.padding()
123-
.textFieldStyle(.roundedBorder)
124-
125-
TextField("Enter Auth Token", text: $vertexAuthToken)
87+
TextField("Enter API Key", text: $claudeAPIKey)
12688
.padding()
12789
.textFieldStyle(.roundedBorder)
12890

129-
Toggle(isOn: $isStreamVertex) {
130-
Text("Enable Stream API")
131-
}
132-
.padding()
133-
13491
NavigationLink {
135-
let claude = AnthropicVertexAIClient(projectId: vertexProjectID, accessToken: vertexAuthToken, region: .europeWest1)
136-
if isStreamVertex {
137-
let observable = StreamViewModel(messageHandler: claude.messages, title: "Stream \\w Vertex")
138-
StreamView(observable: observable)
139-
} else {
140-
let observable = SendViewModel(messageHandler: claude.messages, title: "Message \\w Vertex")
141-
SendView(observable: observable)
142-
}
92+
let claude = Anthropic(apiKey: claudeAPIKey)
93+
let observable = SendMessageBatchesViewModel(messageHandler: claude.messageBatches, title: "Batch \\w Claude")
94+
SendMessageBatchView(observable: observable)
14395
} label: {
14496
Text("Continue")
14597
.frame(maxWidth: .infinity, minHeight: 48)
14698
.foregroundColor(.white)
14799
.background(
148100
Capsule()
149101
.foregroundColor(
150-
vertexProjectID.isEmpty || vertexAuthToken.isEmpty ? .gray.opacity(0.2) : .blue
102+
claudeAPIKey.isEmpty ? .gray.opacity(0.2) : .blue
151103
)
152104
)
153105
}
154106
.padding()
155-
.disabled(vertexProjectID.isEmpty || vertexAuthToken.isEmpty)
107+
.disabled(claudeAPIKey.isEmpty)
156108

157109
Spacer()
158110
}
159-
.navigationTitle("VertexAI Demo")
111+
.navigationTitle("Claude Batch Message Demo")
160112
}
161113
.tabItem {
162-
Image(systemName: "mountain.2.fill")
163-
Text("Vertex")
114+
Image(systemName: "pencil.and.scribble")
115+
Text("Batch Message")
164116
}
165117

166118
}

Example.swiftpm/Extension/Messages+Extension.swift

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,7 @@
77

88
import Foundation
99
import AnthropicSwiftSDK
10-
import AnthropicSwiftSDK_Bedrock
11-
import AnthropicSwiftSDK_VertexAI
1210

1311
extension AnthropicSwiftSDK.Messages: MessageSendable {}
1412
extension AnthropicSwiftSDK.Messages: MessageStreamable {}
15-
extension AnthropicSwiftSDK_Bedrock.Messages: MessageSendable {}
16-
extension AnthropicSwiftSDK_Bedrock.Messages: MessageStreamable {}
17-
extension AnthropicSwiftSDK_VertexAI.Messages: MessageSendable {}
18-
extension AnthropicSwiftSDK_VertexAI.Messages: MessageStreamable {}
13+
extension AnthropicSwiftSDK.MessageBatches: MessageBatchSendable {}

Example.swiftpm/Package.resolved

Lines changed: 9 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Example.swiftpm/Package.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ let package = Package(
1717
name: "Example",
1818
targets: ["AppModule"],
1919
bundleIdentifier: "com.github.fumito-ito.AnthropicSwiftSDK.Example",
20-
teamIdentifier: "L8LPZ499U7",
20+
teamIdentifier: "K489QY5CFD",
2121
displayVersion: "1.0",
2222
bundleVersion: "1",
2323
appIcon: .placeholder(icon: .clock),
@@ -44,9 +44,7 @@ let package = Package(
4444
.executableTarget(
4545
name: "AppModule",
4646
dependencies: [
47-
.product(name: "AnthropicSwiftSDK", package: "AnthropicSwiftSDK"),
48-
.product(name: "AnthropicSwiftSDK-Bedrock", package: "AnthropicSwiftSDK"),
49-
.product(name: "AnthropicSwiftSDK-VertexAI", package: "AnthropicSwiftSDK")
47+
.product(name: "AnthropicSwiftSDK", package: "AnthropicSwiftSDK")
5048
],
5149
path: "."
5250
)

Example.swiftpm/Protocol/MessagesSubject.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ protocol StreamMessagesSubject: MessagesSubject {
3333
func streamMessage(text: String) async throws
3434
}
3535

36+
protocol SendMessageBatchesSubject: MessagesSubject {
37+
init(messageHandler: MessageBatchSendable, title: String, model: Model)
38+
39+
func sendMessageBatch(text: String) async throws
40+
}
41+
3642
protocol MessageSendable {
3743
func createMessage(
3844
_ messages: [Message],
@@ -49,6 +55,12 @@ protocol MessageSendable {
4955
) async throws -> MessagesResponse
5056
}
5157

58+
protocol MessageBatchSendable {
59+
func createBatches(batches: [MessageBatch]) async throws -> BatchResponse
60+
61+
func results(streamOf batchId: String) async throws -> AsyncThrowingStream<BatchResultResponse, Error>
62+
}
63+
5264
protocol MessageStreamable {
5365
func streamMessage(
5466
_ messages: [Message],
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//
2+
// SwiftUIView.swift
3+
// Example
4+
//
5+
// Created by 伊藤史 on 2024/10/25.
6+
//
7+
8+
import SwiftUI
9+
10+
struct SendMessageBatchView: View {
11+
@State var observable: SendMessageBatchesSubject
12+
@State private var prompt = ""
13+
14+
var body: some View {
15+
VStack {
16+
List(observable.messages) { message in
17+
HStack {
18+
if message.user == .assistant {
19+
Image(systemName: "brain.filled.head.profile").frame(alignment: .leading)
20+
Text(message.text).frame(maxWidth: .infinity, alignment: .leading)
21+
22+
} else {
23+
Text(message.text).frame(maxWidth: .infinity, alignment: .trailing)
24+
Image(systemName: "person.fill").frame(alignment: .trailing)
25+
}
26+
}
27+
}
28+
.padding(.bottom, 1)
29+
.alert("Error", isPresented: $observable.isShowingError) {
30+
Button("OK") {}
31+
} message: {
32+
Text(observable.errorMessage)
33+
}
34+
.overlay(
35+
Group {
36+
if observable.isLoading {
37+
ProgressView()
38+
} else {
39+
EmptyView()
40+
}
41+
}
42+
)
43+
}
44+
.safeAreaInset(edge: .bottom) {
45+
VStack(spacing: 0) {
46+
textArea
47+
}
48+
}
49+
.navigationTitle(observable.title)
50+
}
51+
52+
var textArea: some View {
53+
HStack(spacing: 2) {
54+
Button {
55+
observable.clear()
56+
} label: {
57+
Image(systemName: "eraser")
58+
}
59+
.buttonStyle(.bordered)
60+
TextField("Enter prompt", text: $prompt, axis: .vertical)
61+
.textFieldStyle(.roundedBorder)
62+
.padding()
63+
Button {
64+
Task {
65+
do {
66+
try await observable.sendMessageBatch(text: prompt)
67+
} catch {
68+
print(error)
69+
}
70+
}
71+
} label: {
72+
Image(systemName: "paperplane")
73+
}
74+
.buttonStyle(.bordered)
75+
}
76+
.padding()
77+
}
78+
}

0 commit comments

Comments
 (0)