هذا هو عميل Scala Async لا معنى له لـ Openai API يدعم جميع نقاط النهاية والمعلمات المتاحة بما في ذلك البث ، وأحدث إكمال الدردشة ، والرؤية ، والروتين الصوتي (كما هو محدد هنا) ، في خدمة واحدة مريحة تسمى OpenAiservice. المكالمات المدعومة هي:
لاحظ أنه من أجل أن تكون متسقة مع تسمية API Openai ، تتطابق أسماء وظائف الخدمة مع عناوين/أوصاف نهاية API بالضبط مع Camelcase. أيضًا ، كنا نهدف إلى أن تكون LIB قائمة بذاتها مع عدد أقل من التبعيات الممكنة ، لذلك انتهى بنا المطاف باستخدام اثنين فقط من libs play-ahc-ws-standalone
-ws play-ws-standalone-json
(في المستوى الأعلى). بالإضافة إلى ذلك ، إذا كان الحقن التبعية مطلوبًا ، فإننا نستخدم scala-guice
lib أيضًا.
لا وقت لقراءة برنامج تعليمي مطول؟ بالتأكيد ، نسمعك! تحقق من الأمثلة لمعرفة كيفية استخدام lib في الممارسة.
بالإضافة إلى API Openai ، تدعم هذه المكتبة أيضًا مقدمي خدمات API (انظر الأمثلة) مثل:
للحصول على معلومات أساسية ، اقرأ مقالة عن LIB/العميل على المتوسط.
جرب أيضًا عميل Scala الخاص بنا لقاعدة بيانات Pinecone Vector ، أو استخدم كلا العملاء معًا! يوضح هذا المشروع التجريبي كيفية إنشاء وتخزين تضمينات Openai (مع نموذج text-embedding-ada-002
) في pinecone والاستعلام عنها بعد ذلك. يتم استخدام التحرير والسرد Openai + Pinecone بشكل شائع لعوامل الذكاء الاصطناعى المستقلة ، مثل Babyagi و Autogpt.
✔ مهم : هذه مكتبة "تم صيانتها" ، وبالتالي ، ليس لها علاقة بشركة Openai.
إصدارات سكالا المدعومة حاليًا هي 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
(إذا كان لديك واحد)1. الحصول على OpenAiservice
تحتاج أولاً إلى توفير سياق تنفيذ ضمني وكذلك Akka Materializer ، على سبيل المثال ، على سبيل المثال
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 "
)
OpenAICoreService
listModels
، createCompletion
، createChatCompletion
، و createEmbeddings
- المقدمة على سبيل المثال خدمة FastChat تعمل على المنفذ 8000 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 ) {...}
الثاني. وظائف الاتصال
يتم توفير وثائق كاملة لكل مكالمة مع مدخلاتها والإعدادات الخاصة بها في OpenAiservice. نظرًا لأن جميع المكالمات غير متزامنة ، فإنها تعيد الردود ملفوفة في Future
.
هناك أمثلة جديدة للمشروع Openai-Scala-Client-explames حيث يمكنك العثور على الكثير من الأمثلة الجاهزة للاستخدام!
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)
لكي تعمل هذا ، تحتاج إلى استخدام OpenAIServiceStreamedFactory
من openai-scala-client-stream
Lib.
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
. خلاف ذلك ، لن يتم إصدار الموارد/المواضيع الأساسية.
ثالثا. باستخدام المحولات
يتم توفير محولات لـ Openai Services (إكمال الدردشة أو الأساسية أو الكاملة) بواسطة 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 " )} " ))
)
)
ون سكالا 3؟
فبراير 2023. أنت على حق. اخترنا أقصر شهر للقيام بذلك :) منتهي!
حصلت على استثناء مهلة. كيف يمكنني تغيير إعداد المهلة؟
يمكنك القيام بذلك إما عن طريق اجتياز 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
. إذا لم يكن لديك سجل واحد هنا.
كل شيء يبدو رائعا. أريد الدردشة معك حول بحثك وتطويرك؟
ما عليك سوى إطلاق النار علينا بريدًا إلكترونيًا في [email protected].
تتوفر هذه المكتبة ونشرها كمصدر مفتوح بموجب شروط ترخيص معهد ماساتشوستس للتكنولوجيا.
هذا المشروع مفتوح المصدر ويرحب بأي مساهمة أو ردود فعل (هنا).
تم دعم تطوير هذه المكتبة من قبل - cavenence.io - The future of contracting
تم إنشاؤها وصيانتها من قبل بيتر باندا.