Product

OpenAI Scala Client is Out šŸŽ‰

02 Feb 2023
āˆ™

This post was originally published on Medium. Hooray! Coincidentally, it is related to the most hyped thing these days,Ā ChatGPT,Ā and the company behind it ā€”Ā OpenAI.

Long story short, when I was browsing theĀ OpenAI API community libsĀ page earlier this year, to see, which languages are supported, I found out, quite surprisingly, thatĀ Scala, my preferred language for business logic and integration, was missing. As one can expect, I gave aĀ Java client, which can be integrated to Scala (as any other JVM language), a try. Frankly, it worked well, however, it was lacking some idiomatic Scala features (case classes, traits, etc.) and most importantly it was not async. That kept bugging me to the point that Iā€™ve decided to code a client independently. Mainly because it was in line with the mission of my companyĀ Cequence, where I work as CSO.

I find it quite extraordinary and consider myself lucky that Cequence embraced Scala and the functional-programming-mindset in general for its mission to transform Contract Management into an automated, effective environment via ML/NLP-powered features such as contract analytics, risk flagging, and negotiation assistance.

Fast forward a week or two and here it is:Ā OpenAI Scala Client, the very first Scala client for OpenAI API, was released on Jan 25th 2023. Soon after that, it got also listed at theĀ OpenAI community libs page. The project is open-source and is available at GitHub underĀ https://github.com/cequence-io/openai-scala-client. The current version isĀ 0.1.0.

Ā 

If you want to start playing with the lib and check out all the GPT-3 goodies, and/or generate some cool pics with DALL-E, you can do so by adding the following dependency to yourĀ build.sbt:

"io.cequence" %% "openai-scala-client" % "0.1.0"

or toĀ pom.xmlĀ (if you use maven)

<dependency>
<groupId>io.cequence</groupId>
<artifactId>openai-scala-client_2.12</artifactId>
<version>0.1.0</version>
</dependency>

The currently supported Scala versions areĀ 2.12Ā andĀ 2.13Ā but Scala 3-version will come out by the end of February.

All the available functions/endpoints and params (as definedĀ here), are supported in a single, convenient service, which is calledĀ OpenAIService.


Config āš™ļø

The most important environmental variable that you need to set isĀ OPENAI_SCALA_CLIENT_API_KEYĀ and optionally alsoĀ OPENAI_SCALA_CLIENT_ORG_IDĀ (if you have one). Alternatively, you can provide your own config file and override the configuration options (including timeouts) as specified in the default configĀ openai-scala-client.conf.

Usage šŸ‘Øā€šŸŽ“

Before you can even think of doing something (as in most Scala programs) you must define an implicit execution context as well as akka materializer. The simplest way is for instance:

implicit val ec = ExecutionContext.global
implicit val materializer = Materializer(ActorSystem())

Then you can obtain a service in one of the following ways:

I. Obtaining a Service

  • Default configĀ (expects env. variable(s) to be set as defined inĀ Config section
    val service = OpenAIServiceFactory()

  • Custom config
    val config = ConfigFactory.load("path_to_my_custom_config")
    val service = OpenAIServiceFactory(config)

(note that here a config can be also passed through DI, rather than manually created)

  • Without a config file
    val service = OpenAIServiceFactory(
    apiKey = "your_api_key",
    orgId = Some("your_org_id") // if you have one
    )

  • Via dependency injectionĀ (requiresĀ openai-scala-guice lib)
    class MyClass @Inject() (openAIService: OpenAIService) {ā€¦}

II. Calling functions

Full documentation of each call with its respective inputs and settings is provided inĀ OpenAIService. Since all the calls are async they return responses wrapped inĀ Future.

Examples:

  • List models

service.listModels.map(
_.foreach(println)
)

  • Retrieve model

service.retrieveModel(ModelId.text_davinci_003).map(model =>
println(model.getOrElse("N/A"))
)

  • Create completion

val text = """Extract the name and mailing address from this email:
|Dear Kelly,
|It was great to talk to you at the seminar. I thought Janeā€™s talk was quite good.
|Thank you for the book. Hereā€™s my address 2111 Ash Lane, Crestview CA 92002
|Best,
|Maya
""".stripMargin

service.createCompletion(text).map(completion =>
println(completion.choices.head.text)
)

  • Create completion with a custom setting

val text = """Extract the name and mailing address from this email:
|Dear Kelly,
|It was great to talk to you at the seminar. I thought Janeā€™s talk was quite good.
|Thank you for the book. Hereā€™s my address 2111 Ash Lane, Crestview CA 92002
|Best,
|Maya
""".stripMargin

service.createCompletion(
text,
settings = CreateCompletionSettings(
model = ModelId.text_davinci_001,
max_tokens = Some(1500),
temperature = Some(0.9),
presence_penalty = Some(0.2),
frequency_penalty = Some(0.2)
)
).map(completion =>
println(completion.choices.head.text)
)

Ā 

We donā€™t want to be exhaustive here, since in total 20 functions are provided, but itā€™s hopefully enough for you to get an idea: each functionā€™s signature consists of an input (text or image files) and optional settings.

The article was originally published on MEDIUM.Ā 


Discover the full scale of Cequence's capabilities

Join the portfolio of our satisfied customers from large enterprises to medium businesses and learn how to improve your business today.

50,000 + people use Cequence to manage their contracts

DellIntelscantraxx