Skip to content

Commit 9babfa6

Browse files
authored
Merge pull request #84 from cequence-io/feature/3536-latest-TODOs
Feature/3536 latest TODOs
2 parents bb05352 + 63e76a8 commit 9babfa6

File tree

11 files changed

+135
-75
lines changed

11 files changed

+135
-75
lines changed

openai-client/src/main/scala/io/cequence/openaiscala/service/impl/OpenAIServiceImpl.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,7 @@ private[service] trait OpenAIServiceImpl
114114
Param.assistant_id -> Some(assistantId),
115115
Param.thread -> thread.map(Json.toJson(_)),
116116
Param.instructions -> Some(instructions),
117-
// TODO: tools are ignored?
118-
// Param.tools -> Some(Json.toJson(tools)),
117+
Param.tools -> Some(Json.toJson(tools)),
119118
Param.tool_resources -> toolResources.map(Json.toJson(_)),
120119
Param.tool_choice -> toolChoice.map(Json.toJson(_))
121120
)

openai-client/src/test/scala/io/cequence/openaiscala/JsonFormatsSpec.scala

Lines changed: 38 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -46,29 +46,22 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
4646
private val codeInterpreterResourcesJson =
4747
"""{
4848
| "code_interpreter" : {
49-
| "file_ids" : [ {
50-
| "file_id" : "file-id-1"
51-
| }, {
52-
| "file_id" : "file-id-2"
53-
| } ]
49+
| "file_ids" : [ "file-id-1", "file-id-2" ]
5450
| }
5551
|}""".stripMargin
5652

5753
private val fileSearchResourcesJson1 =
5854
"""{
5955
| "file_search" : {
60-
| "vector_store_ids" : [ "vs_xxx" ]
56+
| "vector_store_ids" : [ "vs_xxx", "vs_yyy" ]
6157
| }
6258
|}""".stripMargin
6359

6460
private val fileSearchResourcesJson2 =
6561
"""{
6662
| "file_search" : {
67-
| "vector_store_ids" : [ ],
6863
| "vector_stores" : [ {
69-
| "file_ids" : [ {
70-
| "file_id" : "file-id-1"
71-
| } ],
64+
| "file_ids" : [ "file-id-1" ],
7265
| "metadata" : {
7366
| "key" : "value"
7467
| }
@@ -116,9 +109,7 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
116109

117110
private val attachmentJson =
118111
"""{
119-
| "file_id" : {
120-
| "file_id" : "file-id-1"
121-
| },
112+
| "file_id" : "file-id-1",
122113
| "tools" : [ {
123114
| "type" : "code_interpreter"
124115
| }, {
@@ -187,43 +178,38 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
187178
}
188179

189180
"serialize and deserialize code interpreter's resources" in {
190-
testCodec[AssistantToolResource](
181+
prettyTestCodec[AssistantToolResource](
191182
AssistantToolResource(
192183
CodeInterpreterResources(
193184
Seq(FileId("file-id-1"), FileId("file-id-2"))
194185
)
195186
),
196-
codeInterpreterResourcesJson,
197-
Pretty
187+
codeInterpreterResourcesJson
198188
)
199189
}
200190

201-
// // TODO
202-
// "serialize and deserialize file search's resources with vector store ids" in {
203-
// testCodec[AssistantToolResource](
204-
// AssistantToolResource(
205-
// FileSearchResources(
206-
// vectorStoreIds = Seq("vs_xxx")
207-
// )
208-
// ),
209-
// fileSearchResourcesJson1,
210-
// Pretty
211-
// )
212-
// }
213-
//
214-
// // TODO
215-
// "serialize and deserialize file search's resources with (new) vector stores" in {
216-
// testCodec[AssistantToolResource](
217-
// AssistantToolResource(
218-
// FileSearchResources(
219-
// vectorStoreIds = Nil,
220-
// vectorStores = Seq(VectorStore(Seq(FileId("file-id-1")), Map("key" -> "value")))
221-
// )
222-
// ),
223-
// fileSearchResourcesJson2,
224-
// Pretty
225-
// )
226-
// }
191+
"serialize and deserialize file search's resources with vector store ids" in {
192+
prettyTestCodec[AssistantToolResource](
193+
AssistantToolResource(
194+
FileSearchResources(
195+
vectorStoreIds = Seq("vs_xxx", "vs_yyy")
196+
)
197+
),
198+
fileSearchResourcesJson1
199+
)
200+
}
201+
202+
"serialize and deserialize file search's resources with (new) vector stores" in {
203+
prettyTestCodec[AssistantToolResource](
204+
AssistantToolResource(
205+
FileSearchResources(
206+
vectorStoreIds = Nil,
207+
vectorStores = Seq(VectorStore(Seq(FileId("file-id-1")), Map("key" -> "value")))
208+
)
209+
),
210+
fileSearchResourcesJson2
211+
)
212+
}
227213

228214
"serialize and deserialize run tools" in {
229215
testCodec[RunTool](
@@ -356,9 +342,7 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
356342
testCodec[VectorStore](
357343
vectorStore,
358344
"""{
359-
| "file_ids" : [ {
360-
| "file_id" : "file-123"
361-
| } ],
345+
| "file_ids" : [ "file-123" ],
362346
| "metadata" : {
363347
| "key" : "value"
364348
| }
@@ -493,8 +477,6 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
493477

494478
fineTuneJob.id shouldBe "xxx"
495479
fineTuneJob.model shouldBe "gpt-4o-2024-08-06"
496-
// fineTuneJob.created_at.toString shouldBe "Tue Sep 10 17:52:12 CEST 2024" // TODO:
497-
fineTuneJob.created_at.toString shouldBe "Tue Sep 10 15:52:12 UTC 2024"
498480
fineTuneJob.finished_at shouldBe None
499481
fineTuneJob.fine_tuned_model shouldBe None
500482
fineTuneJob.organization_id shouldBe "org-xxx"
@@ -629,6 +611,15 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
629611
json2 shouldBe value
630612
}
631613

614+
private def prettyTestCodec[A](
615+
value: A,
616+
json: String,
617+
justSemantics: Boolean = false
618+
)(
619+
implicit format: Format[A]
620+
): Unit =
621+
testCodec(value, json, Pretty, justSemantics)
622+
632623
private def testSerialization[A](
633624
value: A,
634625
json: String,

openai-core/src/main/scala/io/cequence/openaiscala/JsonFormats.scala

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,7 @@ object JsonFormats {
260260
case None => json.as[UserSeqMessage]
261261
}
262262

263-
case ChatRole.Tool =>
264-
json.as[ToolMessage]
265-
// TODO: fixed.... originally was
266-
// json.asOpt[AssistantToolMessage] match {
267-
// case Some(assistantToolMessage) => assistantToolMessage
268-
// case None => json.as[ToolMessage]
269-
// }
263+
case ChatRole.Tool => json.as[ToolMessage]
270264

271265
case ChatRole.Assistant =>
272266
// if contains tool_calls, then it is AssistantToolMessage
@@ -650,7 +644,13 @@ object JsonFormats {
650644
implicit lazy val fileSearchResourcesReads
651645
: Reads[AssistantToolResource.FileSearchResources] = {
652646
implicit val config: JsonConfiguration = JsonConfiguration(JsonNaming.SnakeCase)
653-
Json.reads[AssistantToolResource.FileSearchResources]
647+
648+
(
649+
(__ \ "vector_store_ids").readNullable[Seq[String]].map(_.getOrElse(Seq.empty)) and
650+
(__ \ "vector_stores")
651+
.readNullable[Seq[AssistantToolResource.VectorStore]]
652+
.map(_.getOrElse(Seq.empty))
653+
)(AssistantToolResource.FileSearchResources.apply _)
654654
}
655655

656656
implicit lazy val assistantToolResourceReads: Reads[AssistantToolResource] = (
@@ -698,10 +698,10 @@ object JsonFormats {
698698
(__ \ "metadata").read[Map[String, String]].orElse(Reads.pure(Map()))
699699
)(Thread.apply _)
700700

701-
// implicit lazy val threadWrites: Writes[Thread] = Json.writes[Thread]
702-
703-
implicit lazy val fileIdFormat: Format[FileId] =
704-
Json.format[FileId]
701+
implicit val fileIdFormat: Format[FileId] = Format(
702+
Reads.StringReads.map(FileId.apply),
703+
Writes[FileId](fileId => JsString(fileId.file_id))
704+
)
705705

706706
implicit lazy val threadMessageContentTypeFormat: Format[ThreadMessageContentType] =
707707
enumFormat[ThreadMessageContentType](

openai-core/src/main/scala/io/cequence/openaiscala/domain/AssistantToolResource.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ final case class AssistantToolResource(
77

88
object AssistantToolResource {
99

10+
def empty: AssistantToolResource = AssistantToolResource(None, None)
11+
1012
def apply(): AssistantToolResource = AssistantToolResource(None, None)
1113
def apply(codeInterpreterResources: CodeInterpreterResources): AssistantToolResource =
1214
AssistantToolResource(Some(codeInterpreterResources), None)

openai-core/src/main/scala/io/cequence/openaiscala/domain/ThreadAndRun.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import io.cequence.openaiscala.domain.ThreadAndRun.Content.ContentBlock
55
final case class ThreadAndRun(
66
// TODO: check whether the message model is restrictive enough
77
messages: Seq[ThreadAndRun.Message],
8-
toolResources: Seq[AssistantToolResource],
8+
toolResources: AssistantToolResource,
99
metadata: Map[String, Any]
1010
)
1111

openai-core/src/main/scala/io/cequence/openaiscala/service/OpenAIService.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,12 +1227,12 @@ trait OpenAIService extends OpenAICoreService {
12271227
/**
12281228
* Create a vector store.
12291229
*
1230-
* @param file_ids
1230+
* @param fileIds
12311231
* A list of File IDs that the vector store should use (optional). Useful for tools like
12321232
* file_search that can access files.
12331233
* @param name
12341234
* The name of the vector store.
1235-
* @param expires_after
1235+
* @param metadata
12361236
* The expiration policy for a vector store. TODO maximum of 64 characters long and values
12371237
* can be a maximum of 512 characters long.
12381238
* @return
@@ -1244,7 +1244,7 @@ trait OpenAIService extends OpenAICoreService {
12441244
def createVectorStore(
12451245
fileIds: Seq[String] = Nil,
12461246
name: Option[String] = None,
1247-
metadata: Map[String, Any] = Map() // TODO: expires after
1247+
metadata: Map[String, Any] = Map.empty // TODO: expires after
12481248
): Future[VectorStore]
12491249

12501250
/**

openai-examples/src/main/scala/io/cequence/openaiscala/examples/CreateChatCompletion.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package io.cequence.openaiscala.examples
22

3-
import io.cequence.openaiscala.domain.settings.{ChatCompletionResponseFormatType, CreateChatCompletionSettings}
3+
import io.cequence.openaiscala.domain.settings.{
4+
ChatCompletionResponseFormatType,
5+
CreateChatCompletionSettings
6+
}
47
import io.cequence.openaiscala.domain._
58

69
import scala.concurrent.Future
Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package io.cequence.openaiscala.examples
22

3+
import io.cequence.openaiscala.domain.AssistantToolResource.{
4+
CodeInterpreterResources,
5+
FileSearchResources
6+
}
37
import io.cequence.openaiscala.domain.ThreadAndRun.Message.{AssistantMessage, UserMessage}
4-
import io.cequence.openaiscala.domain.ThreadAndRun
8+
import io.cequence.openaiscala.domain.{AssistantToolResource, FileId, ThreadAndRun}
59

610
import scala.concurrent.Future
711

@@ -10,7 +14,7 @@ object CreateThreadAndRun extends Example {
1014
override protected def run: Future[Unit] =
1115
for {
1216
thread <- service.createThreadAndRun(
13-
assistantId = "assistant-abc123",
17+
assistantId = "asst_GEKjNc6lewoiulFt32mWSqKl",
1418
thread = Some(
1519
ThreadAndRun(
1620
messages = Seq(
@@ -20,14 +24,67 @@ object CreateThreadAndRun extends Example {
2024
),
2125
UserMessage("Could you please provide even simpler explanation?")
2226
),
23-
toolResources = Seq.empty,
27+
toolResources = AssistantToolResource.empty,
28+
metadata = Map.empty
29+
)
30+
),
31+
stream = false
32+
)
33+
34+
// Vector Store: CUSTOMER RELATIONSHIP AGREEMENT[vs_sRwpBFIFYyfWQ3og8X9CQs3A] (3 files)
35+
// - file-y5Q8IgmBvQ547z7vi9PDOzZQ (vector_store.file)
36+
// - file-9pb59EqrMCRpDxivmDQ6AxqW (vector_store.file)
37+
// - file-DQQrxLykRzcA54rqMyyfygyV (vector_store.file)
38+
39+
threadWithCodeInterpreter <- service.createThreadAndRun(
40+
assistantId = "asst_GEKjNc6lewoiulFt32mWSqKl",
41+
thread = Some(
42+
ThreadAndRun(
43+
messages = Seq(
44+
UserMessage("Tell me about usage of FP in Cequence."),
45+
AssistantMessage(
46+
"Cequence does use functional programming."
47+
),
48+
UserMessage("Could you please provide more comprehensive answer?")
49+
),
50+
toolResources = AssistantToolResource(
51+
CodeInterpreterResources(fileIds =
52+
Seq(
53+
FileId("file-y5Q8IgmBvQ547z7vi9PDOzZQ"),
54+
FileId("file-9pb59EqrMCRpDxivmDQ6AxqW"),
55+
FileId("file-DQQrxLykRzcA54rqMyyfygyV")
56+
)
57+
)
58+
),
59+
metadata = Map.empty
60+
)
61+
),
62+
stream = false
63+
)
64+
65+
threadWithFileSearch <- service.createThreadAndRun(
66+
assistantId = "asst_GEKjNc6lewoiulFt32mWSqKl",
67+
thread = Some(
68+
ThreadAndRun(
69+
messages = Seq(
70+
UserMessage("Tell me about usage of FP in Cequence."),
71+
AssistantMessage(
72+
"Cequence does use functional programming."
73+
),
74+
UserMessage("Could you please provide more comprehensive answer?")
75+
),
76+
toolResources = AssistantToolResource(
77+
FileSearchResources(vectorStoreIds = Seq("vs_sRwpBFIFYyfWQ3og8X9CQs3A"))
78+
),
2479
metadata = Map.empty
2580
)
2681
),
2782
stream = false
2883
)
2984
} yield {
3085
println(thread)
86+
println(threadWithCodeInterpreter)
87+
println(threadWithFileSearch)
3188
}
3289

3390
}
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.cequence.openaiscala.examples
22

3+
import io.cequence.openaiscala.domain.VectorStoreFile
4+
35
import scala.concurrent.Future
46

57
object ListVectorStoreFiles extends Example {
@@ -9,14 +11,20 @@ object ListVectorStoreFiles extends Example {
911
vectorStores <- service.listVectorStores()
1012

1113
vectorStoreChunks = vectorStores.sliding(10, 10).toList
12-
_ = vectorStoreChunks.map(_.map(x => (x.id, x.name))).foreach(println)
13-
files <- Future.traverse(vectorStoreChunks) { vectorStoresChunk =>
14+
vsAndFiles <- Future.traverse(vectorStoreChunks) { vectorStoresChunk =>
1415
Future.traverse(vectorStoresChunk) { vectorStore =>
15-
service.listVectorStoreFiles(vectorStore.id).map(file => (vectorStore.name, file))
16+
service
17+
.listVectorStoreFiles(vectorStore.id)
18+
.map((files: Seq[VectorStoreFile]) => (vectorStore, files))
1619
}
1720
}
1821

1922
} yield {
20-
files.foreach(println)
23+
vsAndFiles.flatten.foreach { case (vs, files) =>
24+
println(s"Vector Store: ${vs.name}[${vs.id}] (${files.length} files)")
25+
files.foreach { file =>
26+
println(s" - ${file.id} (${file.`object`})")
27+
}
28+
}
2129
}
2230
}

openai-examples/src/main/scala/io/cequence/openaiscala/examples/RetrieveVectorStore.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ object RetrieveVectorStore extends Example {
77
override protected def run: Future[_] =
88
for {
99
assistant <- service.retrieveVectorStore(
10-
vectorStoreId = "vs_xxx"
10+
vectorStoreId = "vs_9pl9kTn3ggjzDKYX5AT9JuIG"
1111
)
1212
} yield {
1313
println(assistant)

0 commit comments

Comments
 (0)