- Notifications
You must be signed in to change notification settings - Fork35
Scala client for OpenAI API and other major LLM providers
License
cequence-io/openai-scala-client
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This is a no-nonsense async Scala client for OpenAI API supporting all the available endpoints and paramsincluding streaming, the newestchat completion,responses API,assistants API,tools,vision, andvoice routines (as definedhere), provided in a single, convenient service calledOpenAIService. The supported calls are:
- Models:listModels, andretrieveModel
- Completions:createCompletion
- Chat Completions:createChatCompletion,createChatFunCompletion (deprecated), andcreateChatToolCompletion
- Edits:createEdit (deprecated)
- Images:createImage,createImageEdit, andcreateImageVariation
- Embeddings:createEmbeddings
- Batches:createBatch,retrieveBatch,cancelBatch, andlistBatches
- Audio:createAudioTranscription,createAudioTranslation, andcreateAudioSpeech
- Files:listFiles,uploadFile,deleteFile,retrieveFile, andretrieveFileContent
- Fine-tunes:createFineTune,listFineTunes,retrieveFineTune,cancelFineTune,listFineTuneEvents,listFineTuneCheckpoints, anddeleteFineTuneModel
- Moderations:createModeration
- Assistants:createAssistant,listAssistants,retrieveAssistant,modifyAssistant, anddeleteAssistant
- Threads:createThread,retrieveThread,modifyThread, anddeleteThread
- Thread Messages:createThreadMessage,retrieveThreadMessage,modifyThreadMessage,listThreadMessages,retrieveThreadMessageFile, andlistThreadMessageFiles
- Runs:createRun,createThreadAndRun,listRuns,retrieveRun,modifyRun,submitToolOutputs, andcancelRun
- Run Steps:listRunSteps, andretrieveRunStep
- Vector Stores:createVectorStore,listVectorStores,retrieveVectorStore,modifyVectorStore, anddeleteVectorStore
- Vector Store Files:createVectorStoreFile,listVectorStoreFiles,retrieveVectorStoreFile, anddeleteVectorStoreFile
- Vector Store File Batches:createVectorStoreFileBatch,retrieveVectorStoreFileBatch,cancelVectorStoreFileBatch, andlistVectorStoreBatchFiles
- Responses (🔥New):createModelResponse,getModelResponse,deleteModelResponse, andlistModelResponseInputItems
Note that in order to be consistent with the OpenAI API naming, the service function names match exactly the API endpoint titles/descriptions in camelCase.Also, we aimed for the library to be self-contained with the fewest dependencies possible. Therefore, we implemented our own generic WS client (currently with Play WS backend, which can be swapped for other engines in the future). Additionally, if dependency injection is required, we use thescala-guice library.
👉No time to read a lengthy tutorial? Sure, we hear you! Check out theexamples to see how to use the lib in practice.
In addition to OpenAI, this library supports many other LLM providers. For providers that aren't natively compatible with the chat completion API, we've implemented adapters to streamline integration (seeexamples).
| Provider | JSON/Structured Output | Tools Support | Description |
|---|---|---|---|
| OpenAI | Full | Standard + Responses API | Full API support |
| Azure OpenAI | Full | Standard + Responses API | OpenAI on Azure |
| Anthropic | Implied | Claude models | |
| Azure AI | Varies | Open-source models | |
| Cerebras | Only JSON object mode | Fast inference | |
| Deepseek | Only JSON object mode | Chinese provider | |
| FastChat | Varies | Local LLMs | |
| Fireworks AI | Only JSON object mode | Cloud provider | |
| Google Gemini (🔥New) | Full | Yes | Google's models |
| Google Vertex AI | Full | Yes | Gemini models |
| Grok | Full | x.AI models | |
| Groq | Only JSON object mode | Fast inference | |
| Mistral | Only JSON object mode | Open-source leader | |
| Novita (🔥New) | Only JSON object mode | Cloud provider | |
| Octo AI | Only JSON object mode | Cloud provider (obsolete) | |
| Ollama | Varies | Local LLMs | |
| Perplexity Sonar (🔥New) | Only implied | Search-based AI | |
| TogetherAI | Only JSON object mode | Cloud provider |
👉 For background information how the project started read an article about the lib/client onMedium.
Also try out ourScala client for Pinecone vector database, or use both clients together!This demo project shows how to generate and store OpenAI embeddings into Pinecone and query them afterward. The OpenAI + Pinecone combo is commonly used for autonomous AI agents, such asbabyAGI andAutoGPT.
✔️ Important: this is a "community-maintained" library and, as such, has no relation to OpenAI company.
The currently supported Scala versions are2.12, 2.13, and3.
To install the library, add the following dependency to yourbuild.sbt
"io.cequence" %% "openai-scala-client" % "1.3.0.RC.1"or topom.xml (if you use maven)
<dependency> <groupId>io.cequence</groupId> <artifactId>openai-scala-client_2.12</artifactId> <version>1.3.0.RC.1</version></dependency>If you want streaming support, use"io.cequence" %% "openai-scala-client-stream" % "1.3.0.RC.1" instead.
- Env. variables:
OPENAI_SCALA_CLIENT_API_KEYand optionally alsoOPENAI_SCALA_CLIENT_ORG_ID(if you have one) - File config (default):openai-scala-client.conf
I. Obtaining OpenAIService
First you need to provide an implicit execution context as well as akka materializer, e.g., as
implicitvalec=ExecutionContext.globalimplicitvalmaterializer=Materializer(ActorSystem())
Then you can obtain a service in one of the following ways.
- Default config (expects env. variable(s) to be set as defined in
Configsection)
valservice=OpenAIServiceFactory()
- Custom config
valconfig=ConfigFactory.load("path_to_my_custom_config")valservice=OpenAIServiceFactory(config)
- Without config
valservice=OpenAIServiceFactory( apiKey="your_api_key", orgId=Some("your_org_id")// if you have one )
- ForAzure with API Key
valservice=OpenAIServiceFactory.forAzureWithApiKey( resourceName="your-resource-name", deploymentId="your-deployment-id",// usually model name such as "gpt-35-turbo" apiVersion="2023-05-15",// newest version apiKey="your_api_key" )
- Minimal
OpenAICoreServicesupportinglistModels,createCompletion,createChatCompletion, andcreateEmbeddingscalls - provided e.g. byFastChat service running on the port 8000
valservice=OpenAICoreServiceFactory("http://localhost:8000/v1/")
OpenAIChatCompletionServiceproviding solelycreateChatCompletion
- Azure AI - e.g. Cohere R+ model
valservice=OpenAIChatCompletionServiceFactory.forAzureAI( endpoint= sys.env("AZURE_AI_COHERE_R_PLUS_ENDPOINT"), region= sys.env("AZURE_AI_COHERE_R_PLUS_REGION"), accessToken= sys.env("AZURE_AI_COHERE_R_PLUS_ACCESS_KEY") )
- Anthropic - requires
openai-scala-anthropic-clientlib andANTHROPIC_API_KEY
valservice=AnthropicServiceFactory.asOpenAI()// or AnthropicServiceFactory.bedrockAsOpenAI
- Google Vertex AI - requires
openai-scala-google-vertexai-clientlib andVERTEXAI_LOCATION+VERTEXAI_PROJECT_ID
valservice=VertexAIServiceFactory.asOpenAI()
- Google Gemini - requires
openai-scala-google-gemini-clientlib andGOOGLE_API_KEY
valservice=GeminiServiceFactory.asOpenAI()
- Perplexity Sonar - requires
openai-scala-perplexity-clientlib andSONAR_API_KEY
valservice=SonarServiceFactory.asOpenAI()
- Novita - requires
NOVITA_API_KEY
valservice=OpenAIChatCompletionServiceFactory(ChatProviderSettings.novita)// or with streamingvalservice=OpenAIChatCompletionServiceFactory.withStreaming(ChatProviderSettings.novita)
- Groq - requires
GROQ_API_KEY"
valservice=OpenAIChatCompletionServiceFactory(ChatProviderSettings.groq)// or with streamingvalservice=OpenAIChatCompletionServiceFactory.withStreaming(ChatProviderSettings.groq)
- Grok - requires
GROK_API_KEY"
valservice=OpenAIChatCompletionServiceFactory(ChatProviderSettings.grok)// or with streamingvalservice=OpenAIChatCompletionServiceFactory.withStreaming(ChatProviderSettings.grok)
- Fireworks AI - requires
FIREWORKS_API_KEY"
valservice=OpenAIChatCompletionServiceFactory(ChatProviderSettings.fireworks)// or with streamingvalservice=OpenAIChatCompletionServiceFactory.withStreaming(ChatProviderSettings.fireworks)
- Octo AI - requires
OCTOAI_TOKEN
valservice=OpenAIChatCompletionServiceFactory(ChatProviderSettings.octoML)// or with streamingvalservice=OpenAIChatCompletionServiceFactory.withStreaming(ChatProviderSettings.octoML)
- TogetherAI requires
TOGETHERAI_API_KEY
valservice=OpenAIChatCompletionServiceFactory(ChatProviderSettings.togetherAI)// or with streamingvalservice=OpenAIChatCompletionServiceFactory.withStreaming(ChatProviderSettings.togetherAI)
- Cerebras requires
CEREBRAS_API_KEY
valservice=OpenAIChatCompletionServiceFactory(ChatProviderSettings.cerebras)// or with streamingvalservice=OpenAIChatCompletionServiceFactory.withStreaming(ChatProviderSettings.cerebras)
- Mistral requires
MISTRAL_API_KEY
valservice=OpenAIChatCompletionServiceFactory(ChatProviderSettings.mistral)// or with streamingvalservice=OpenAIChatCompletionServiceFactory.withStreaming(ChatProviderSettings.mistral)
valservice=OpenAIChatCompletionServiceFactory( coreUrl="http://localhost:11434/v1/" )
or with streaming
valservice=OpenAIChatCompletionServiceFactory.withStreaming( coreUrl="http://localhost:11434/v1/" )
- Note that services with additional streaming support -
createCompletionStreamedandcreateChatCompletionStreamedprovided byOpenAIStreamedServiceExtra (requiresopenai-scala-client-streamlib)
importio.cequence.openaiscala.service.StreamedServiceTypes.OpenAIStreamedServiceimportio.cequence.openaiscala.service.OpenAIStreamedServiceImplicits._valservice:OpenAIStreamedService=OpenAIServiceFactory.withStreaming()
similarly for a chat-completion service
importio.cequence.openaiscala.service.OpenAIStreamedServiceImplicits._valservice=OpenAIChatCompletionServiceFactory.withStreaming( coreUrl="https://api.fireworks.ai/inference/v1/", authHeaders=Seq(("Authorization",s"Bearer${sys.env("FIREWORKS_API_KEY")}")) )
or only if streaming is required
valservice:OpenAIChatCompletionStreamedServiceExtra=OpenAIChatCompletionStreamedServiceFactory( coreUrl="https://api.fireworks.ai/inference/v1/", authHeaders=Seq(("Authorization",s"Bearer${sys.env("FIREWORKS_API_KEY")}")) )
- Via dependency injection (requires
openai-scala-guicelib)
classMyClass@Inject() (openAIService:OpenAIService) {...}
II. Calling functions
Full documentation of each call with its respective inputs and settings is provided inOpenAIService. Since all the calls are async they return responses wrapped inFuture.
There is a new projectopenai-scala-client-examples where you can find a lot of ready-to-use examples!
- List models
service.listModels.map(models=> models.foreach(println) )- Retrieve model
service.retrieveModel(ModelId.text_davinci_003).map(model=> println(model.getOrElse("N/A")) )
- Create chat completion
valcreateChatCompletionSettings=CreateChatCompletionSettings( model=ModelId.gpt_4o )valmessages=Seq(SystemMessage("You are a helpful assistant."),UserMessage("Who won the world series in 2020?"),AssistantMessage("The Los Angeles Dodgers won the World Series in 2020."),UserMessage("Where was it played?"), ) service.createChatCompletion( messages= messages, settings= createChatCompletionSettings ).map { chatCompletion=> println(chatCompletion.contentHead) }
- Create chat completion for functions
valmessages=Seq(SystemMessage("You are a helpful assistant."),UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?") )// as a param type we can use "number", "string", "boolean", "object", "array", and "null"valtools=Seq(FunctionSpec( name="get_current_weather", description=Some("Get the current weather in a given location"), parameters=Map("type"->"object","properties"->Map("location"->Map("type"->"string","description"->"The city and state, e.g. San Francisco, CA" ),"unit"->Map("type"->"string","enum"->Seq("celsius","fahrenheit") ) ),"required"->Seq("location") ) ) )// if we want to force the model to use the above function as a response// we can do so by passing: responseToolChoice = Some("get_current_weather")` service.createChatToolCompletion( messages= messages, tools= tools, responseToolChoice=None,// means "auto" settings=CreateChatCompletionSettings(ModelId.gpt_4o) ).map { response=>valchatFunCompletionMessage= response.choices.head.messagevaltoolCalls= chatFunCompletionMessage.tool_calls.collect {case (id,x:FunctionCallSpec)=> (id, x) } println("tool call ids :"+ toolCalls.map(_._1).mkString(",") ) println("function/tool call names :"+ toolCalls.map(_._2.name).mkString(",") ) println("function/tool call arguments :"+ toolCalls.map(_._2.arguments).mkString(",") ) }
- Create chat completion withJSON/structured output
valmessages=Seq(SystemMessage("Give me the most populous capital cities in JSON format."),UserMessage("List only african countries") )valcapitalsSchema=JsonSchema.Object( properties=Map("countries"->JsonSchema.Array( items=JsonSchema.Object( properties=Map("country"->JsonSchema.String( description=Some("The name of the country") ),"capital"->JsonSchema.String( description=Some("The capital city of the country") ) ), required=Seq("country","capital") ) ) ), required=Seq("countries") )valjsonSchemaDef=JsonSchemaDef( name="capitals_response", strict=true, structure= capitalsSchema ) service .createChatCompletion( messages= messages, settings=CreateChatCompletionSettings( model=ModelId.o3_mini, max_tokens=Some(1000), response_format_type=Some(ChatCompletionResponseFormatType.json_schema), jsonSchema=Some(jsonSchemaDef) ) ) .map { response=>valjson=Json.parse(response.contentHead) println(Json.prettyPrint(json)) }
- Create chat completion withJSON/structured output using a handly implicit function (
createChatCompletionWithJSON[T]) that handles JSON extraction with a potential repair, as well as deserialization to an object T.
importio.cequence.openaiscala.service.OpenAIChatCompletionExtra._ ... service .createChatCompletionWithJSON[JsObject]( messages= messages, settings=CreateChatCompletionSettings( model=ModelId.o3_mini, max_tokens=Some(1000), response_format_type=Some(ChatCompletionResponseFormatType.json_schema), jsonSchema=Some(jsonSchemaDef) ) ) .map { json=> println(Json.prettyPrint(json)) }
- Failover to alternative models if the primary one fails
importio.cequence.openaiscala.service.OpenAIChatCompletionExtra._valmessages=Seq(SystemMessage("You are a helpful weather assistant."),UserMessage("What is the weather like in Norway?") ) service .createChatCompletionWithFailover( messages= messages, settings=CreateChatCompletionSettings( model=ModelId.o3_mini ), failoverModels=Seq(ModelId.gpt_4_5_preview,ModelId.gpt_4o), retryOnAnyError=true, failureMessage="Weather assistant failed to provide a response." ) .map { response=> print(response.contentHead) }
- Failover with JSON/structured output
importio.cequence.openaiscala.service.OpenAIChatCompletionExtra._valcapitalsSchema=JsonSchema.Object( properties=Map("countries"->JsonSchema.Array( items=JsonSchema.Object( properties=Map("country"->JsonSchema.String( description=Some("The name of the country") ),"capital"->JsonSchema.String( description=Some("The capital city of the country") ) ), required=Seq("country","capital") ) ) ), required=Seq("countries") )valjsonSchemaDef=JsonSchemaDef( name="capitals_response", strict=true, structure= capitalsSchema )// Define the chat messagesvalmessages=Seq(SystemMessage("Give me the most populous capital cities in JSON format."),UserMessage("List only african countries") )// Call the service with failover support service .createChatCompletionWithJSON[JsObject]( messages= messages, settings=CreateChatCompletionSettings( model=ModelId.o3_mini,// Primary model max_tokens=Some(1000), response_format_type=Some(ChatCompletionResponseFormatType.json_schema), jsonSchema=Some(jsonSchemaDef) ), failoverModels=Seq(ModelId.gpt_4_5_preview,// First fallback modelModelId.gpt_4o// Second fallback model ), maxRetries=Some(3),// Maximum number of retries per model retryOnAnyError=true,// Retry on any error, not just retryable ones taskNameForLogging=Some("capitals-query")// For better logging ) .map { json=> println(Json.prettyPrint(json)) }
- Responses API - basic usage with textual inputs / messages
importio.cequence.openaiscala.domain.responsesapi.Inputs service .createModelResponse(Inputs.Text("What is the capital of France?") ) .map { response=> println(response.outputText.getOrElse("N/A")) }
importio.cequence.openaiscala.domain.responsesapi.Input service .createModelResponse(Inputs.Items(Input.ofInputSystemTextMessage("You are a helpful assistant. Be verbose and detailed and don't be afraid to use emojis." ),Input.ofInputUserTextMessage("What is the capital of France?") ) ) .map { response=> println(response.outputText.getOrElse("N/A")) }
- Responses API - image input
importio.cequence.openaiscala.domain.responsesapi.{Inputs,Input}importio.cequence.openaiscala.domain.responsesapi.InputMessageContentimportio.cequence.openaiscala.domain.ChatRole service .createModelResponse(Inputs.Items(Input.ofInputMessage(Seq(InputMessageContent.Text("what is in this image?"),InputMessageContent.Image( imageUrl=Some("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" ) ) ), role=ChatRole.User ) ) ) .map { response=> println(response.outputText.getOrElse("N/A")) }
- Responses API - tool use (file search)
service .createModelResponse(Inputs.Text("What are the attributes of an ancient brown dragon?"), settings=CreateModelResponseSettings( model=ModelId.gpt_4o_2024_08_06, tools=Seq(FileSearchTool( vectorStoreIds=Seq("vs_1234567890"), maxNumResults=Some(20), filters=None, rankingOptions=None ) ) ) ) .map { response=> println(response.outputText.getOrElse("N/A"))// citationsvalcitations:Seq[Annotation.FileCitation]= response.outputMessageContents.collect {casee:OutputText=> e.annotations.collect {casecitation:Annotation.FileCitation=> citation } }.flatten println("Citations:") citations.foreach { citation=> println(s"${citation.fileId} -${citation.filename}") } }
- Responses API - tool use (web search)
service .createModelResponse(Inputs.Text("What was a positive news story from today?"), settings=CreateModelResponseSettings( model=ModelId.gpt_4o_2024_08_06, tools=Seq(WebSearchTool()) ) ) .map { response=> println(response.outputText.getOrElse("N/A"))// citationsvalcitations:Seq[Annotation.UrlCitation]= response.outputMessageContents.collect {casee:OutputText=> e.annotations.collect {casecitation:Annotation.UrlCitation=> citation } }.flatten println("Citations:") citations.foreach { citation=> println(s"${citation.title} -${citation.url}") } }
- Responses API - tool use (function call)
service .createModelResponse(Inputs.Text("What is the weather like in Boston today?"), settings=CreateModelResponseSettings( model=ModelId.gpt_4o_2024_08_06, tools=Seq(FunctionTool( name="get_current_weather", parameters=JsonSchema.Object( properties=Map("location"->JsonSchema.String( description=Some("The city and state, e.g. San Francisco, CA") ),"unit"->JsonSchema.String( `enum`=Seq("celsius","fahrenheit") ) ), required=Seq("location","unit") ), description=Some("Get the current weather in a given location"), strict=true ) ), toolChoice=Some(ToolChoice.Mode.Auto) ) ) .map { response=>valfunctionCall= response.outputFunctionCalls.headOption .getOrElse(thrownewRuntimeException("No function call output found")) println(s"""Function Call Details: |Name:${functionCall.name} |Arguments:${functionCall.arguments} |Call ID:${functionCall.callId} |ID:${functionCall.id} |Status:${functionCall.status}""".stripMargin )valtoolsUsed= response.tools.map(_.typeString) println(s"${toolsUsed.size} tools used:${toolsUsed.mkString(",")}") }
- Count expected used tokens before calling
createChatCompletionsorcreateChatFunCompletions, this helps you select proper model and reduce costs. This is an experimental feature and it may not work for all models. Requiresopenai-scala-count-tokenslib.
An example how to count message tokens:
importio.cequence.openaiscala.service.OpenAICountTokensHelperimportio.cequence.openaiscala.domain.{AssistantMessage,BaseMessage,FunctionSpec,ModelId,SystemMessage,UserMessage}classMyCompletionServiceextendsOpenAICountTokensHelper {defexec= {valmodel=ModelId.gpt_4_turbo_2024_04_09// messages to be sent to OpenAIvalmessages:Seq[BaseMessage]=Seq(SystemMessage("You are a helpful assistant."),UserMessage("Who won the world series in 2020?"),AssistantMessage("The Los Angeles Dodgers won the World Series in 2020."),UserMessage("Where was it played?"), )valtokenCount= countMessageTokens(model, messages) }}
An example how to count message tokens when a function is involved:
importio.cequence.openaiscala.service.OpenAICountTokensHelperimportio.cequence.openaiscala.domain.{BaseMessage,FunctionSpec,ModelId,SystemMessage,UserMessage}classMyCompletionServiceextendsOpenAICountTokensHelper {defexec= {valmodel=ModelId.gpt_4_turbo_2024_04_09// messages to be sent to OpenAIvalmessages:Seq[BaseMessage]=Seq(SystemMessage("You are a helpful assistant."),UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?") )// function to be calledvalfunction:FunctionSpec=FunctionSpec( name="getWeather", parameters=Map("type"->"object","properties"->Map("location"->Map("type"->"string","description"->"The city to get the weather for" ),"unit"->Map("type"->"string","enum"->List("celsius","fahrenheit")) ) ) )valtokenCount= countFunMessageTokens(model, messages,Seq(function),Some(function.name)) }}
✔️ Important: After you are done using the service, you should close it by callingservice.close. Otherwise, the underlying resources/threads won't be released.
III. Using adapters
Adapters for OpenAI services (chat completion, core, or full) are provided byOpenAIServiceAdapters. The adapters are used to distribute the load between multiple services, retry on transient errors, route, or provide additional functionality. Seeexamples for more details.
Note that the adapters can be arbitrarily combined/stacked.
- Round robin load distribution
valadapters=OpenAIServiceAdapters.forFullServicevalservice1=OpenAIServiceFactory("your-api-key1")valservice2=OpenAIServiceFactory("your-api-key2")valservice= adapters.roundRobin(service1, service2)
- Random order load distribution
valadapters=OpenAIServiceAdapters.forFullServicevalservice1=OpenAIServiceFactory("your-api-key1")valservice2=OpenAIServiceFactory("your-api-key2")valservice= adapters.randomOrder(service1, service2)
- Logging function calls
valadapters=OpenAIServiceAdapters.forFullServicevalrawService=OpenAIServiceFactory()valservice= adapters.log( rawService,"openAIService", logger.log )
- Retry on transient errors (e.g. rate limit error)
valadapters=OpenAIServiceAdapters.forFullServiceimplicitvalretrySettings:RetrySettings=RetrySettings(maxRetries=10).constantInterval(10.seconds)valservice= adapters.retry(OpenAIServiceFactory(),Some(println(_))// simple logging )
- Retry on a specific function usingRetryHelpers directly
classMyCompletionService@Inject() (valactorSystem:ActorSystem,implicitvalec:ExecutionContext,implicitvalscheduler:Scheduler)(valapiKey:String)extendsRetryHelpers {valservice:OpenAIService=OpenAIServiceFactory(apiKey)implicitvalretrySettings:RetrySettings=RetrySettings(interval=10.seconds)defask(prompt:String):Future[String]=for { completion<- service .createChatCompletion(List(MessageSpec(ChatRole.User, prompt)) ) .retryOnFailure }yield completion.choices.head.message.content}
- Route chat completion calls based on models
valadapters=OpenAIServiceAdapters.forFullService// OctoAIvaloctoMLService=OpenAIChatCompletionServiceFactory( coreUrl="https://text.octoai.run/v1/", authHeaders=Seq(("Authorization",s"Bearer${sys.env("OCTOAI_TOKEN")}")) )// AnthropicvalanthropicService=AnthropicServiceFactory.asOpenAI()// OpenAIvalopenAIService=OpenAIServiceFactory()valservice:OpenAIService= adapters.chatCompletionRouter(// OpenAI service is default so no need to specify its models here serviceModels=Map( octoMLService->Seq(NonOpenAIModelId.mixtral_8x22b_instruct), anthropicService->Seq(NonOpenAIModelId.claude_2_1,NonOpenAIModelId.claude_3_opus_20240229,NonOpenAIModelId.claude_3_haiku_20240307 ) ), openAIService )
- Chat-to-completion adapter
valadapters=OpenAIServiceAdapters.forCoreServicevalservice= adapters.chatToCompletion(OpenAICoreServiceFactory( coreUrl="https://api.fireworks.ai/inference/v1/", authHeaders=Seq(("Authorization",s"Bearer${sys.env("FIREWORKS_API_KEY")}")) ) )
Wen Scala 3?
Feb 2023. You are right; we chose the shortest month to do so :)Done!I got a timeout exception. How can I change the timeout setting?
You can do it either by passing the
timeoutsparam toOpenAIServiceFactoryor, if you use your own configuration file, then you can simply add it there as:
openai-scala-client { timeouts { requestTimeoutSec = 200 readTimeoutSec = 200 connectTimeoutSec = 5 pooledConnectionIdleTimeoutSec = 60 }}I got an exception like
com.typesafe.config.ConfigException$UnresolvedSubstitution: openai-scala-client.conf @ jar:file:.../io/cequence/openai-scala-client_2.13/0.0.1/openai-scala-client_2.13-0.0.1.jar!/openai-scala-client.conf: 4: Could not resolve substitution to a value: ${OPENAI_SCALA_CLIENT_API_KEY}. What should I do?Set the env. variable
OPENAI_SCALA_CLIENT_API_KEY. If you don't have one registerhere.It all looks cool. I want to chat with you about your research and development?
Just shoot us an email atopenai-scala-client@cequence.io.
This library is available and published as open source under the terms of theMIT License.
This project is open-source and welcomes any contribution or feedback (here).
Development of this library has been supported by - Cequence.io -
The future of contracting
Created and maintained byPeter Banda.
About
Scala client for OpenAI API and other major LLM providers
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors8
Uh oh!
There was an error while loading.Please reload this page.