Skip to content

Commit 67cc20a

Browse files
authored
Merge pull request #38 from phiHero/conversation
feat: add conversation API & doc: update README API documentation
2 parents f0f1c03 + 900c067 commit 67cc20a

16 files changed

+661
-30
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
mkdir $(pwd)/typesense-data
3333
docker run -p 8108:8108 \
3434
-d \
35-
-v$(pwd)/typesense-data:/data typesense/typesense:27.0.rc35 \
35+
-v$(pwd)/typesense-data:/data typesense/typesense:27.0 \
3636
--data-dir /data \
3737
--api-key=xyz \
3838
--enable-cors

README.md

Lines changed: 195 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,134 @@ let (data, response) = try await client.collection(name: "schools").documents().
8686

8787
This returns a `SearchResult` object as the data, which can be further parsed as desired.
8888

89+
### Bulk import documents
90+
91+
```swift
92+
let jsonL = Data("{}".utf8)
93+
let (data, response) = try await client.collection(name: "companies").documents().importBatch(jsonL, options: ImportDocumentsParameters(
94+
action: .upsert,
95+
batchSize: 10,
96+
dirtyValues: .drop,
97+
remoteEmbeddingBatchSize: 10,
98+
returnDoc: true,
99+
returnId: false
100+
))
101+
```
102+
103+
### Update multiple documents by query
104+
105+
```swift
106+
let (data, response) = try await client.collection(name: "companies").documents().update(
107+
document: ["company_size": "large"],
108+
options: UpdateDocumentsByFilterParameters(filterBy: "num_employees:>1000")
109+
)
110+
```
111+
112+
### Delete multiple documents by query
113+
114+
```swift
115+
let (data, response) = try await client.collection(name: "companies").documents().delete(
116+
options: DeleteDocumentsParameters(filterBy: "num_employees:>100")
117+
)
118+
```
119+
120+
### Export documents
121+
122+
```swift
123+
let (data, response) = try await client.collection(name: "companies").documents().export(options: ExportDocumentsParameters(excludeFields: "country"))
124+
```
125+
126+
### Create or update a collection alias
127+
128+
```swift
129+
let schema = CollectionAliasSchema(collectionName: "companies_june")
130+
let (data, response) = try await client.aliases().upsert(name: "companies", collection: schema)
131+
```
132+
133+
### Retrieve all aliases
134+
135+
```swift
136+
let (data, response) = try await client.aliases().retrieve()
137+
```
138+
139+
### Retrieve an alias
140+
141+
```swift
142+
let (data, response) = try await client.aliases().retrieve(name: "companies")
143+
```
144+
145+
### Delete an alias
146+
147+
```swift
148+
let (data, response) = try await client.aliases().delete(name: "companies")
149+
```
150+
151+
### Create an API key
152+
153+
```swift
154+
let adminKey = ApiKeySchema(_description: "Test key with all privileges", actions: ["*"], collections: ["*"])
155+
let (data, response) = try await client.keys().create(adminKey)
156+
```
157+
158+
### Retrieve all API keys
159+
160+
```swift
161+
let (data, response) = try await client.keys().retrieve()
162+
```
163+
164+
### Retrieve an API key
165+
166+
```swift
167+
let (data, response) = try await client.keys().retrieve(id: 1)
168+
```
169+
170+
### Delete an API key
171+
172+
```swift
173+
let (data, response) = try await client.keys().delete(id: 1)
174+
```
175+
176+
### Create a conversation model
177+
178+
```swift
179+
let schema = ConversationModelCreateSchema(
180+
_id: "conv-model-1",
181+
modelName: "openai/gpt-3.5-turbo",
182+
apiKey: "OPENAI_API_KEY",
183+
historyCollection: "conversation_store",
184+
systemPrompt: "You are an assistant for question-answering...",
185+
ttl: 10000,
186+
maxBytes: 16384
187+
)
188+
let (data, response) = try await client.conversations().models().create(params: schema)
189+
```
190+
191+
### Retrieve all conversation models
192+
193+
```swift
194+
let (data, response) = try await client.conversations().models().retrieve()
195+
```
196+
197+
### Retrieve a conversation model
198+
199+
```swift
200+
let (data, response) = try await client.conversations().model(modelId: "conv-model-1").retrieve()
201+
```
202+
203+
### Update a conversation model
204+
205+
```swift
206+
let (data, response) = try await client.conversations().model(modelId: "conv-model-1").update(params: ConversationModelUpdateSchema(
207+
systemPrompt: "..."
208+
))
209+
```
210+
211+
### Delete a conversation model
212+
213+
```swift
214+
let (data, response) = try await client.conversations().model(modelId: "conv-model-1").delete()
215+
```
216+
89217
### Create or update an override
90218

91219
```swift
@@ -187,12 +315,79 @@ let (data, response) = try await client.stopword("stopword_set1").retrieve()
187315
let (data, response) = try await client.stopword("stopword_set1").delete()
188316
```
189317

318+
### Create or update a synonym
319+
320+
```swift
321+
let schema = SearchSynonymSchema(synonyms: ["blazer", "coat", "jacket"])
322+
let (data, response) = try await client.collection(name: "products").synonyms().upsert(id: "coat-synonyms", schema)
323+
```
324+
325+
### Retrieve all synonyms
326+
327+
```swift
328+
let (data, response) = try await client.collection(name: "products").synonyms().retrieve()
329+
```
330+
331+
### Retrieve a synonym
332+
333+
```swift
334+
let (data, response) = try await client.collection(name: "products").synonyms().retrieve(id: "coat-synonyms")
335+
```
336+
337+
### Delete a synonym
338+
339+
```swift
340+
let (data, response) = try await myClient.collection(name: "products").synonyms().delete(id: "coat-synonyms")
341+
```
342+
190343
### Retrieve debug information
191344

192345
```swift
193346
let (data, response) = try await client.operations().getDebug()
194347
```
195348

349+
### Retrieve health status
350+
351+
```swift
352+
let (data, response) = try await client.operations().getHealth()
353+
```
354+
355+
### Retrieve API stats
356+
357+
```swift
358+
let (data, response) = try await client.operations().getStats()
359+
```
360+
361+
### Retrieve Cluster Metrics
362+
363+
```swift
364+
let (data, response) = try await client.operations().getMetrics()
365+
```
366+
367+
### Re-elect Leader
368+
369+
```swift
370+
let (data, response) = try await client.operations().vote()
371+
```
372+
373+
### Toggle Slow Request Log
374+
375+
```swift
376+
let (data, response) = try await client.operations().toggleSlowRequestLog(seconds: 2)
377+
```
378+
379+
### Clear cache
380+
381+
```swift
382+
let (data, response) = try await client.operations().clearCache()
383+
```
384+
385+
### Create Snapshot (for backups)
386+
387+
```swift
388+
let (data, response) = try await client.operations().snapshot(path: "/tmp/typesense-data-snapshot")
389+
```
390+
196391
## Contributing
197392

198393
Issues and pull requests are welcome on GitHub at [Typesense Swift](https://github.com/typesense/typesense-swift). Do note that the Models used in the Swift client are generated by [Swagger-Codegen](https://github.com/swagger-api/swagger-codegen) and are automated to be modified in order to prevent major errors. So please do use the shell script that is provided in the repo to generate the models:
@@ -205,5 +400,4 @@ The generated Models (inside the Models directory) are to be used inside the Mod
205400

206401
## TODO: Features
207402

208-
- Dealing with Dirty Data
209403
- Scoped Search Key

Sources/Typesense/Client.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ public struct Client {
1616
return Collection(apiCall: apiCall, collectionName: name)
1717
}
1818

19+
public func conversations() -> Conversations {
20+
return Conversations(apiCall: apiCall)
21+
}
22+
1923
public func keys() -> ApiKeys {
2024
return ApiKeys(apiCall: apiCall)
2125
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import Foundation
2+
#if canImport(FoundationNetworking)
3+
import FoundationNetworking
4+
#endif
5+
6+
public struct ConversationModel {
7+
private var apiCall: ApiCall
8+
var modelId: String
9+
10+
init(apiCall: ApiCall, modelId: String) {
11+
self.apiCall = apiCall
12+
self.modelId = modelId
13+
}
14+
15+
public func update(params: ConversationModelUpdateSchema) async throws -> (ConversationModelSchema?, URLResponse?) {
16+
let schemaData = try encoder.encode(params)
17+
let (data, response) = try await self.apiCall.put(endPoint: endpointPath(), body: schemaData)
18+
if let result = data {
19+
let decodedData = try decoder.decode(ConversationModelSchema.self, from: result)
20+
return (decodedData, response)
21+
}
22+
return (nil, response)
23+
}
24+
25+
public func retrieve() async throws -> (ConversationModelSchema?, URLResponse?) {
26+
let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
27+
if let result = data {
28+
let decodedData = try decoder.decode(ConversationModelSchema.self, from: result)
29+
return (decodedData, response)
30+
}
31+
return (nil, response)
32+
}
33+
34+
public func delete() async throws -> (ConversationModelSchema?, URLResponse?) {
35+
let (data, response) = try await self.apiCall.delete(endPoint: endpointPath())
36+
if let result = data {
37+
let decodedData = try decoder.decode(ConversationModelSchema.self, from: result)
38+
return (decodedData, response)
39+
}
40+
return (nil, response)
41+
}
42+
43+
private func endpointPath() throws -> String {
44+
return try "\(Conversations.RESOURCE_PATH)/\(ConversationModels.RESOURCE_PATH)/\(modelId.encodeURL())"
45+
}
46+
47+
48+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import Foundation
2+
#if canImport(FoundationNetworking)
3+
import FoundationNetworking
4+
#endif
5+
6+
public struct ConversationModels {
7+
static let RESOURCE_PATH = "models"
8+
private var apiCall: ApiCall
9+
10+
11+
init(apiCall: ApiCall) {
12+
self.apiCall = apiCall
13+
}
14+
15+
public func create(params: ConversationModelCreateSchema) async throws -> (ConversationModelSchema?, URLResponse?) {
16+
let schemaData = try encoder.encode(params)
17+
let (data, response) = try await self.apiCall.post(endPoint: endpointPath(), body: schemaData)
18+
if let result = data {
19+
let decodedData = try decoder.decode(ConversationModelSchema.self, from: result)
20+
return (decodedData, response)
21+
}
22+
return (nil, response)
23+
}
24+
25+
public func retrieve() async throws -> ([ConversationModelSchema]?, URLResponse?) {
26+
let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
27+
if let result = data {
28+
let decodedData = try decoder.decode([ConversationModelSchema].self, from: result)
29+
return (decodedData, response)
30+
}
31+
return (nil, response)
32+
}
33+
34+
private func endpointPath() throws -> String {
35+
return "\(Conversations.RESOURCE_PATH)/\(ConversationModels.RESOURCE_PATH)"
36+
}
37+
38+
39+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Foundation
2+
3+
public struct Conversations {
4+
static let RESOURCE_PATH = "conversations"
5+
private var apiCall: ApiCall
6+
7+
8+
init(apiCall: ApiCall) {
9+
self.apiCall = apiCall
10+
}
11+
12+
public func models() -> ConversationModels {
13+
return ConversationModels(apiCall: apiCall)
14+
}
15+
16+
public func model(modelId: String) -> ConversationModel {
17+
return ConversationModel(apiCall: apiCall, modelId: modelId)
18+
}
19+
20+
}

0 commit comments

Comments
 (0)