Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ private[service] trait OpenAIServiceImpl
Param.assistant_id -> Some(assistantId),
Param.thread -> thread.map(Json.toJson(_)),
Param.instructions -> Some(instructions),
// TODO: tools are ignored?
// Param.tools -> Some(Json.toJson(tools)),
Param.tools -> Some(Json.toJson(tools)),
Param.tool_resources -> toolResources.map(Json.toJson(_)),
Param.tool_choice -> toolChoice.map(Json.toJson(_))
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,29 +46,22 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
private val codeInterpreterResourcesJson =
"""{
| "code_interpreter" : {
| "file_ids" : [ {
| "file_id" : "file-id-1"
| }, {
| "file_id" : "file-id-2"
| } ]
| "file_ids" : [ "file-id-1", "file-id-2" ]
| }
|}""".stripMargin

private val fileSearchResourcesJson1 =
"""{
| "file_search" : {
| "vector_store_ids" : [ "vs_xxx" ]
| "vector_store_ids" : [ "vs_xxx", "vs_yyy" ]
| }
|}""".stripMargin

private val fileSearchResourcesJson2 =
"""{
| "file_search" : {
| "vector_store_ids" : [ ],
| "vector_stores" : [ {
| "file_ids" : [ {
| "file_id" : "file-id-1"
| } ],
| "file_ids" : [ "file-id-1" ],
| "metadata" : {
| "key" : "value"
| }
Expand Down Expand Up @@ -116,9 +109,7 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {

private val attachmentJson =
"""{
| "file_id" : {
| "file_id" : "file-id-1"
| },
| "file_id" : "file-id-1",
| "tools" : [ {
| "type" : "code_interpreter"
| }, {
Expand Down Expand Up @@ -187,43 +178,38 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
}

"serialize and deserialize code interpreter's resources" in {
testCodec[AssistantToolResource](
prettyTestCodec[AssistantToolResource](
AssistantToolResource(
CodeInterpreterResources(
Seq(FileId("file-id-1"), FileId("file-id-2"))
)
),
codeInterpreterResourcesJson,
Pretty
codeInterpreterResourcesJson
)
}

// // TODO
// "serialize and deserialize file search's resources with vector store ids" in {
// testCodec[AssistantToolResource](
// AssistantToolResource(
// FileSearchResources(
// vectorStoreIds = Seq("vs_xxx")
// )
// ),
// fileSearchResourcesJson1,
// Pretty
// )
// }
//
// // TODO
// "serialize and deserialize file search's resources with (new) vector stores" in {
// testCodec[AssistantToolResource](
// AssistantToolResource(
// FileSearchResources(
// vectorStoreIds = Nil,
// vectorStores = Seq(VectorStore(Seq(FileId("file-id-1")), Map("key" -> "value")))
// )
// ),
// fileSearchResourcesJson2,
// Pretty
// )
// }
"serialize and deserialize file search's resources with vector store ids" in {
prettyTestCodec[AssistantToolResource](
AssistantToolResource(
FileSearchResources(
vectorStoreIds = Seq("vs_xxx", "vs_yyy")
)
),
fileSearchResourcesJson1
)
}

"serialize and deserialize file search's resources with (new) vector stores" in {
prettyTestCodec[AssistantToolResource](
AssistantToolResource(
FileSearchResources(
vectorStoreIds = Nil,
vectorStores = Seq(VectorStore(Seq(FileId("file-id-1")), Map("key" -> "value")))
)
),
fileSearchResourcesJson2
)
}

"serialize and deserialize run tools" in {
testCodec[RunTool](
Expand Down Expand Up @@ -356,9 +342,7 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
testCodec[VectorStore](
vectorStore,
"""{
| "file_ids" : [ {
| "file_id" : "file-123"
| } ],
| "file_ids" : [ "file-123" ],
| "metadata" : {
| "key" : "value"
| }
Expand Down Expand Up @@ -493,8 +477,6 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {

fineTuneJob.id shouldBe "xxx"
fineTuneJob.model shouldBe "gpt-4o-2024-08-06"
// fineTuneJob.created_at.toString shouldBe "Tue Sep 10 17:52:12 CEST 2024" // TODO:
fineTuneJob.created_at.toString shouldBe "Tue Sep 10 15:52:12 UTC 2024"
fineTuneJob.finished_at shouldBe None
fineTuneJob.fine_tuned_model shouldBe None
fineTuneJob.organization_id shouldBe "org-xxx"
Expand Down Expand Up @@ -629,6 +611,15 @@ class JsonFormatsSpec extends AnyWordSpecLike with Matchers {
json2 shouldBe value
}

private def prettyTestCodec[A](
value: A,
json: String,
justSemantics: Boolean = false
)(
implicit format: Format[A]
): Unit =
testCodec(value, json, Pretty, justSemantics)

private def testSerialization[A](
value: A,
json: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,7 @@ object JsonFormats {
case None => json.as[UserSeqMessage]
}

case ChatRole.Tool =>
json.as[ToolMessage]
// TODO: fixed.... originally was
// json.asOpt[AssistantToolMessage] match {
// case Some(assistantToolMessage) => assistantToolMessage
// case None => json.as[ToolMessage]
// }
case ChatRole.Tool => json.as[ToolMessage]

case ChatRole.Assistant =>
// if contains tool_calls, then it is AssistantToolMessage
Expand Down Expand Up @@ -650,7 +644,13 @@ object JsonFormats {
implicit lazy val fileSearchResourcesReads
: Reads[AssistantToolResource.FileSearchResources] = {
implicit val config: JsonConfiguration = JsonConfiguration(JsonNaming.SnakeCase)
Json.reads[AssistantToolResource.FileSearchResources]

(
(__ \ "vector_store_ids").readNullable[Seq[String]].map(_.getOrElse(Seq.empty)) and
(__ \ "vector_stores")
.readNullable[Seq[AssistantToolResource.VectorStore]]
.map(_.getOrElse(Seq.empty))
)(AssistantToolResource.FileSearchResources.apply _)
}

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

// implicit lazy val threadWrites: Writes[Thread] = Json.writes[Thread]

implicit lazy val fileIdFormat: Format[FileId] =
Json.format[FileId]
implicit val fileIdFormat: Format[FileId] = Format(
Reads.StringReads.map(FileId.apply),
Writes[FileId](fileId => JsString(fileId.file_id))
)

implicit lazy val threadMessageContentTypeFormat: Format[ThreadMessageContentType] =
enumFormat[ThreadMessageContentType](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ final case class AssistantToolResource(

object AssistantToolResource {

def empty: AssistantToolResource = AssistantToolResource(None, None)

def apply(): AssistantToolResource = AssistantToolResource(None, None)
def apply(codeInterpreterResources: CodeInterpreterResources): AssistantToolResource =
AssistantToolResource(Some(codeInterpreterResources), None)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.cequence.openaiscala.domain.ThreadAndRun.Content.ContentBlock
final case class ThreadAndRun(
// TODO: check whether the message model is restrictive enough
messages: Seq[ThreadAndRun.Message],
toolResources: Seq[AssistantToolResource],
toolResources: AssistantToolResource,
metadata: Map[String, Any]
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1227,12 +1227,12 @@ trait OpenAIService extends OpenAICoreService {
/**
* Create a vector store.
*
* @param file_ids
* @param fileIds
* A list of File IDs that the vector store should use (optional). Useful for tools like
* file_search that can access files.
* @param name
* The name of the vector store.
* @param expires_after
* @param metadata
* The expiration policy for a vector store. TODO maximum of 64 characters long and values
* can be a maximum of 512 characters long.
* @return
Expand All @@ -1244,7 +1244,7 @@ trait OpenAIService extends OpenAICoreService {
def createVectorStore(
fileIds: Seq[String] = Nil,
name: Option[String] = None,
metadata: Map[String, Any] = Map() // TODO: expires after
metadata: Map[String, Any] = Map.empty // TODO: expires after
): Future[VectorStore]

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package io.cequence.openaiscala.examples

import io.cequence.openaiscala.domain.settings.{ChatCompletionResponseFormatType, CreateChatCompletionSettings}
import io.cequence.openaiscala.domain.settings.{
ChatCompletionResponseFormatType,
CreateChatCompletionSettings
}
import io.cequence.openaiscala.domain._

import scala.concurrent.Future
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package io.cequence.openaiscala.examples

import io.cequence.openaiscala.domain.AssistantToolResource.{
CodeInterpreterResources,
FileSearchResources
}
import io.cequence.openaiscala.domain.ThreadAndRun.Message.{AssistantMessage, UserMessage}
import io.cequence.openaiscala.domain.ThreadAndRun
import io.cequence.openaiscala.domain.{AssistantToolResource, FileId, ThreadAndRun}

import scala.concurrent.Future

Expand All @@ -10,7 +14,7 @@ object CreateThreadAndRun extends Example {
override protected def run: Future[Unit] =
for {
thread <- service.createThreadAndRun(
assistantId = "assistant-abc123",
assistantId = "asst_GEKjNc6lewoiulFt32mWSqKl",
thread = Some(
ThreadAndRun(
messages = Seq(
Expand All @@ -20,14 +24,67 @@ object CreateThreadAndRun extends Example {
),
UserMessage("Could you please provide even simpler explanation?")
),
toolResources = Seq.empty,
toolResources = AssistantToolResource.empty,
metadata = Map.empty
)
),
stream = false
)

// Vector Store: CUSTOMER RELATIONSHIP AGREEMENT[vs_sRwpBFIFYyfWQ3og8X9CQs3A] (3 files)
// - file-y5Q8IgmBvQ547z7vi9PDOzZQ (vector_store.file)
// - file-9pb59EqrMCRpDxivmDQ6AxqW (vector_store.file)
// - file-DQQrxLykRzcA54rqMyyfygyV (vector_store.file)

threadWithCodeInterpreter <- service.createThreadAndRun(
assistantId = "asst_GEKjNc6lewoiulFt32mWSqKl",
thread = Some(
ThreadAndRun(
messages = Seq(
UserMessage("Tell me about usage of FP in Cequence."),
AssistantMessage(
"Cequence does use functional programming."
),
UserMessage("Could you please provide more comprehensive answer?")
),
toolResources = AssistantToolResource(
CodeInterpreterResources(fileIds =
Seq(
FileId("file-y5Q8IgmBvQ547z7vi9PDOzZQ"),
FileId("file-9pb59EqrMCRpDxivmDQ6AxqW"),
FileId("file-DQQrxLykRzcA54rqMyyfygyV")
)
)
),
metadata = Map.empty
)
),
stream = false
)

threadWithFileSearch <- service.createThreadAndRun(
assistantId = "asst_GEKjNc6lewoiulFt32mWSqKl",
thread = Some(
ThreadAndRun(
messages = Seq(
UserMessage("Tell me about usage of FP in Cequence."),
AssistantMessage(
"Cequence does use functional programming."
),
UserMessage("Could you please provide more comprehensive answer?")
),
toolResources = AssistantToolResource(
FileSearchResources(vectorStoreIds = Seq("vs_sRwpBFIFYyfWQ3og8X9CQs3A"))
),
metadata = Map.empty
)
),
stream = false
)
} yield {
println(thread)
println(threadWithCodeInterpreter)
println(threadWithFileSearch)
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.cequence.openaiscala.examples

import io.cequence.openaiscala.domain.VectorStoreFile

import scala.concurrent.Future

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

vectorStoreChunks = vectorStores.sliding(10, 10).toList
_ = vectorStoreChunks.map(_.map(x => (x.id, x.name))).foreach(println)
files <- Future.traverse(vectorStoreChunks) { vectorStoresChunk =>
vsAndFiles <- Future.traverse(vectorStoreChunks) { vectorStoresChunk =>
Future.traverse(vectorStoresChunk) { vectorStore =>
service.listVectorStoreFiles(vectorStore.id).map(file => (vectorStore.name, file))
service
.listVectorStoreFiles(vectorStore.id)
.map((files: Seq[VectorStoreFile]) => (vectorStore, files))
}
}

} yield {
files.foreach(println)
vsAndFiles.flatten.foreach { case (vs, files) =>
println(s"Vector Store: ${vs.name}[${vs.id}] (${files.length} files)")
files.foreach { file =>
println(s" - ${file.id} (${file.`object`})")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ object RetrieveVectorStore extends Example {
override protected def run: Future[_] =
for {
assistant <- service.retrieveVectorStore(
vectorStoreId = "vs_xxx"
vectorStoreId = "vs_9pl9kTn3ggjzDKYX5AT9JuIG"
)
} yield {
println(assistant)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ object RetrieveVectorStoreFile extends Example {
override protected def run: Future[_] =
for {
assistant <- service.retrieveVectorStoreFile(
vectorStoreId = "vs_xxx",
vectorStoreId = "vs_9pl9kTn3ggjzDKYX5AT9JuIG",
fileId = FileId("vsf_xxx")
)
} yield {
Expand Down
Loading