これは、OpenaIserviceと呼ばれる単一の便利なサービスで提供されるストリーミング、最新のチャット完了、ビジョン、音声ルーチン(ここで定義)など、利用可能なすべてのエンドポイントとパラメーションをサポートするOpenAI APIのナンセンスな非同期クライアントです。サポートされている呼び出しは次のとおりです。
OpenAI APIネーミングと一致するために、サービス関数名はAPIエンドポイントのタイトル/説明とCamelCaseと正確に一致することに注意してください。また、LIBは、可能な限り少ない依存関係で自己完結型であることを目指しました。したがって、最終的には2つのLIBS play-ahc-ws-standalone
とplay-ws-standalone-json
(トップレベル)のみを使用しました。さらに、依存関係注射が必要な場合はscala-guice
Libも使用します。
長いチュートリアルを読む時間はありませんか?確かに、私たちはあなたを聞きます!例をチェックして、libを実際に使用する方法を確認してください。
Openai APIに加えて、このライブラリは次のようなAPI互換プロバイダー(例を参照)もサポートしています。
背景情報については、媒体上のLIB/クライアントに関する記事をご覧ください。
また、Pinecone VectorデータベースのSCALAクライアントを試してみるか、両方のクライアントを一緒に使用してください!このデモプロジェクトは、OpenAI埋め込み( text-embedding-ada-002
モデルを使用)を生成して保存し、その後それらを照会する方法を示しています。 Openai + Pineconeコンボは、BabyagiやAutogptなどの自律AIエージェントに一般的に使用されています。
重要:これは「コミュニティに維持された」ライブラリであり、そのため、Openai Companyとは関係ありません。
現在サポートされているSCALAバージョンは2.12、2.13 、および3です。
ライブラリをインストールするには、 build.sbtに次の依存関係を追加します。
"io.cequence" %% "openai-scala-client" % "1.1.0"
またはpom.xml (mavenを使用している場合)
<dependency>
<groupId>io.cequence</groupId>
<artifactId>openai-scala-client_2.12</artifactId>
<version>1.1.0</version>
</dependency>
ストリーミングサポートが必要な場合は、代わりに"io.cequence" %% "openai-scala-client-stream" % "1.1.0"
を使用します。
OPENAI_SCALA_CLIENT_API_KEY
およびオプションでもOPENAI_SCALA_CLIENT_ORG_ID
(持っている場合)I. OpenaIserviceの取得
まず、暗黙の実行コンテキストとAkka Materalizerを提供する必要があります。
implicit val ec = ExecutionContext .global
implicit val materializer = Materializer ( ActorSystem ())
次に、次の方法のいずれかでサービスを取得できます。
Config
セクションで定義されているように設定されると予想されます) val service = OpenAIServiceFactory ()
val config = ConfigFactory .load( " path_to_my_custom_config " )
val service = OpenAIServiceFactory (config)
val service = OpenAIServiceFactory (
apiKey = " your_api_key " ,
orgId = Some ( " your_org_id " ) // if you have one
)
val service = 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 "
)
listModels
、 createCompletion
、 createChatCompletion
、およびcreateEmbeddings
Callをサポートする最小限のOpenAICoreService
- ポート8000で実行されているFastChat Serviceが提供する val service = OpenAICoreServiceFactory ( " http://localhost:8000/v1/ " )
OpenAIChatCompletionService
、 createChatCompletion
のみを提供します val service = 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 " )
)
openai-scala-anthropic-client
libとANTHROPIC_API_KEY
が必要です val service = AnthropicServiceFactory .asOpenAI()
openai-scala-google-vertexai-client
libおよびVERTEXAI_LOCATION
+ VERTEXAI_PROJECT_ID
が必要です val service = VertexAIServiceFactory .asOpenAI()
GROQ_API_KEY"
val service = OpenAIChatCompletionServiceFactory ( ChatProviderSettings .groq)
// or with streaming
val service = OpenAIChatCompletionServiceFactory .withStreaming( ChatProviderSettings .groq)
GROK_API_KEY"
val service = OpenAIChatCompletionServiceFactory ( ChatProviderSettings .grok)
// or with streaming
val service = OpenAIChatCompletionServiceFactory .withStreaming( ChatProviderSettings .grok)
FIREWORKS_API_KEY"
val service = OpenAIChatCompletionServiceFactory ( ChatProviderSettings .fireworks)
// or with streaming
val service = OpenAIChatCompletionServiceFactory .withStreaming( ChatProviderSettings .fireworks)
OCTOAI_TOKEN
が必要です val service = OpenAIChatCompletionServiceFactory ( ChatProviderSettings .octoML)
// or with streaming
val service = OpenAIChatCompletionServiceFactory .withStreaming( ChatProviderSettings .octoML)
TOGETHERAI_API_KEY
に必要です val service = OpenAIChatCompletionServiceFactory ( ChatProviderSettings .togetherAI)
// or with streaming
val service = OpenAIChatCompletionServiceFactory .withStreaming( ChatProviderSettings .togetherAI)
CEREBRAS_API_KEY
が必要です val service = OpenAIChatCompletionServiceFactory ( ChatProviderSettings .cerebras)
// or with streaming
val service = OpenAIChatCompletionServiceFactory .withStreaming( ChatProviderSettings .cerebras)
MISTRAL_API_KEY
が必要です val service = OpenAIChatCompletionServiceFactory ( ChatProviderSettings .mistral)
// or with streaming
val service = OpenAIChatCompletionServiceFactory .withStreaming( ChatProviderSettings .mistral)
val service = OpenAIChatCompletionServiceFactory (
coreUrl = " http://localhost:11434/v1/ "
)
またはストリーミング付き
val service = OpenAIChatCompletionServiceFactory .withStreaming(
coreUrl = " http://localhost:11434/v1/ "
)
createCompletionStreamed
およびcreateChatCompletionStreamed
OpenAistreamEdServiceExtraによって提供されたことに注意してください( openai-scala-client-stream
Libが必要です) import io . cequence . openaiscala . service . StreamedServiceTypes . OpenAIStreamedService
import io . cequence . openaiscala . service . OpenAIStreamedServiceImplicits . _
val service : OpenAIStreamedService = OpenAIServiceFactory .withStreaming()
同様に、チャット完了サービスの場合
import io . cequence . openaiscala . service . OpenAIStreamedServiceImplicits . _
val service = OpenAIChatCompletionServiceFactory .withStreaming(
coreUrl = " https://api.fireworks.ai/inference/v1/ " ,
authHeaders = Seq (( " Authorization " , s " Bearer ${sys.env( " FIREWORKS_API_KEY " )} " ))
)
または、ストリーミングが必要な場合のみ
val service : OpenAIChatCompletionStreamedServiceExtra =
OpenAIChatCompletionStreamedServiceFactory (
coreUrl = " https://api.fireworks.ai/inference/v1/ " ,
authHeaders = Seq (( " Authorization " , s " Bearer ${sys.env( " FIREWORKS_API_KEY " )} " ))
)
openai-scala-guice
libが必要です) class MyClass @ Inject () ( openAIService : OpenAIService ) {...}
ii。呼び出し関数
それぞれの入力と設定を備えた各コールの完全なドキュメントは、OpenAiServiceで提供されています。すべての呼び出しは非同期であるため、 Future
に包まれた応答を返します。
多くのすぐに使用できる例を見つけることができる新しいプロジェクトOpenai-Scala-Client-Examplesがあります!
service.listModels.map(models =>
models.foreach(println)
)
service.retrieveModel( ModelId .text_davinci_003).map(model =>
println(model.getOrElse( " N/A " ))
)
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)
)
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 .gpt_4o,
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)
)
val source = service.createCompletionStreamed(
prompt = " Write me a Shakespeare poem about two cats playing baseball in Russia using at least 2 pages " ,
settings = CreateCompletionSettings (
model = ModelId .text_davinci_003,
max_tokens = Some ( 1500 ),
temperature = Some ( 0.9 ),
presence_penalty = Some ( 0.2 ),
frequency_penalty = Some ( 0.2 )
)
)
source.map(completion =>
println(completion.choices.head.text)
).runWith( Sink .ignore)
これを機能させるにはopenai-scala-client-stream
LibのOpenAIServiceStreamedFactory
を使用する必要があります。
val createChatCompletionSettings = CreateChatCompletionSettings (
model = ModelId .gpt_4o
)
val messages = 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.choices.head.message.content)
}
val messages = 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"
val tools = 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_3_5_turbo_1106)
).map { response =>
val chatFunCompletionMessage = response.choices.head.message
val toolCalls = 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( " , " )
)
}
val messages = Seq (
SystemMessage ( " Give me the most populous capital cities in JSON format. " ),
UserMessage ( " List only african countries " )
)
val capitalsSchema = 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 " )
)
val jsonSchemaDef = JsonSchemaDef (
name = " capitals_response " ,
strict = true ,
structure = schema
)
service
.createChatCompletion(
messages = messages,
settings = DefaultSettings .createJsonChatCompletion(jsonSchemaDef)
)
.map { response =>
val json = Json .parse(messageContent(response))
println( Json .prettyPrint(json))
}
createChatCompletions
またはcreateChatFunCompletions
を呼び出す前に、予想される使用されたトークンをカウントします。これにより、適切なモデルを選択してコストを削減できます。これは実験機能であり、すべてのモデルで機能しない場合があります。 openai-scala-count-tokens
Libが必要です。メッセージトークンをカウントする方法:
import io . cequence . openaiscala . service . OpenAICountTokensHelper
import io . cequence . openaiscala . domain .{ AssistantMessage , BaseMessage , FunctionSpec , ModelId , SystemMessage , UserMessage }
class MyCompletionService extends OpenAICountTokensHelper {
def exec = {
val model = ModelId .gpt_4_turbo_2024_04_09
// messages to be sent to OpenAI
val messages : 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? " ),
)
val tokenCount = countMessageTokens(model, messages)
}
}
機能が関係しているときにメッセージトークンをカウントする方法:
import io . cequence . openaiscala . service . OpenAICountTokensHelper
import io . cequence . openaiscala . domain .{ BaseMessage , FunctionSpec , ModelId , SystemMessage , UserMessage }
class MyCompletionService extends OpenAICountTokensHelper {
def exec = {
val model = ModelId .gpt_4_turbo_2024_04_09
// messages to be sent to OpenAI
val messages : Seq [ BaseMessage ] =
Seq (
SystemMessage ( " You are a helpful assistant. " ),
UserMessage ( " What's the weather like in San Francisco, Tokyo, and Paris? " )
)
// function to be called
val function : 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 " ))
)
)
)
val tokenCount = countFunMessageTokens(model, messages, Seq (function), Some (function.name))
}
}
重要:サービスを使用して完了したら、 service.close
を呼び出して閉じる必要があります。それ以外の場合、基礎となるリソース/スレッドはリリースされません。
iii。アダプターを使用します
OpenAIサービス用のアダプター(チャット完了、コア、またはフル)は、OpenaiServiceAdaptersによって提供されます。アダプターは、複数のサービス間で負荷を配布したり、過渡エラーで再試行したり、ルートを変更したり、追加の機能を提供したりするために使用されます。詳細については、例をご覧ください。
アダプターは任意に結合/積み重ねることができることに注意してください。
val adapters = OpenAIServiceAdapters .forFullService
val service1 = OpenAIServiceFactory ( " your-api-key1 " )
val service2 = OpenAIServiceFactory ( " your-api-key2 " )
val service = adapters.roundRobin(service1, service2)
val adapters = OpenAIServiceAdapters .forFullService
val service1 = OpenAIServiceFactory ( " your-api-key1 " )
val service2 = OpenAIServiceFactory ( " your-api-key2 " )
val service = adapters.randomOrder(service1, service2)
val adapters = OpenAIServiceAdapters .forFullService
val rawService = OpenAIServiceFactory ()
val service = adapters.log(
rawService,
" openAIService " ,
logger.log
)
val adapters = OpenAIServiceAdapters .forFullService
implicit val retrySettings : RetrySettings = RetrySettings (maxRetries = 10 ).constantInterval( 10 .seconds)
val service = adapters.retry(
OpenAIServiceFactory (),
Some (println(_)) // simple logging
)
class MyCompletionService @ Inject () (
val actorSystem : ActorSystem ,
implicit val ec : ExecutionContext ,
implicit val scheduler : Scheduler
)( val apiKey : String )
extends RetryHelpers {
val service : OpenAIService = OpenAIServiceFactory (apiKey)
implicit val retrySettings : RetrySettings =
RetrySettings (interval = 10 .seconds)
def ask ( prompt : String ) : Future [ String ] =
for {
completion < - service
.createChatCompletion(
List ( MessageSpec ( ChatRole . User , prompt))
)
.retryOnFailure
} yield completion.choices.head.message.content
}
val adapters = OpenAIServiceAdapters .forFullService
// OctoAI
val octoMLService = OpenAIChatCompletionServiceFactory (
coreUrl = " https://text.octoai.run/v1/ " ,
authHeaders = Seq (( " Authorization " , s " Bearer ${sys.env( " OCTOAI_TOKEN " )} " ))
)
// Anthropic
val anthropicService = AnthropicServiceFactory .asOpenAI()
// OpenAI
val openAIService = OpenAIServiceFactory ()
val service : 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
)
val adapters = OpenAIServiceAdapters .forCoreService
val service = adapters.chatToCompletion(
OpenAICoreServiceFactory (
coreUrl = " https://api.fireworks.ai/inference/v1/ " ,
authHeaders = Seq (( " Authorization " , s " Bearer ${sys.env( " FIREWORKS_API_KEY " )} " ))
)
)
wen scala3?
2023年2月。あなたは正しいです。私たちはそうするために最短月を選びました:)終わり!
タイムアウトの例外がありました。タイムアウト設定を変更するにはどうすればよいですか?
timeouts
ParamをOpenAIServiceFactory
に渡すか、独自の構成ファイルを使用する場合は、次のように追加できます。
openai-scala-client {
timeouts {
requestTimeoutSec = 200
readTimeoutSec = 200
connectTimeoutSec = 5
pooledConnectionIdleTimeoutSec = 60
}
}
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}
。どうすればいいですか?
envを設定します。可変OPENAI_SCALA_CLIENT_API_KEY
。ここに1つの登録がない場合。
それはすべてクールに見えます。私はあなたの研究開発についてあなたとチャットしたいですか?
[email protected]でメールを撮影してください。
このライブラリは、MITライセンスの条件の下でオープンソースとして利用可能であり、公開されています。
このプロジェクトはオープンソースであり、貢献やフィードバックを歓迎します(こちら)。
このライブラリの開発は-cequence.io- The future of contracting
によってサポートされています
Peter Bandaによって作成および維持されています。