이것은 OpenAiservice라는 단일의 편리한 서비스로 제공되는 스트리밍 , 최신 채팅 완료 , 비전 및 음성 루틴 (여기에서 정의 된대로)을 포함한 모든 사용 가능한 엔드 포인트 및 매개 변수를 지원하는 OpenAI API를위한 말도 안되는 비스듬한 스칼라 클라이언트입니다. 지원되는 통화는 다음과 같습니다.
OpenAI API 명명과 일치하기 위해 서비스 기능 이름은 API 엔드 포인트 제목/설명과 Camelcase와 정확히 일치합니다. 또한, 우리는 LIB가 가능한 가장 적은 의존성에 독립적 인 것을 목표로 삼았으므로 결국 두 개의 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
모델 포함)을 Pinecone에 생성하고 저장하는 방법을 보여줍니다. Openai + Pinecone 콤보는 일반적으로 Babyagi 및 Autogpt와 같은 자율 AI 에이전트에 사용됩니다.
✔️ 중요한 : 이것은 "커뮤니티 관리 된"도서관이며 OpenAI 회사와 관련이 없습니다.
현재 지원되는 스칼라 버전은 2.12, 2.13 및 3 입니다.
라이브러리를 설치하려면 빌드 에 다음 의존성을 추가하십시오 .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 Materializer와 같은
implicit val ec = ExecutionContext .global
implicit val materializer = Materializer ( ActorSystem ())
그런 다음 다음 방법 중 하나로 서비스를 얻을 수 있습니다.
Config
섹션에 정의 된대로 설정할 Env. 변수 예상) 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
호출을 지원하는 최소 OpenAICoreService
- 포트 8000에서 실행되는 Fastchat 서비스에 의해 제공되는 최소 openaicoreservice 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-Poomples가 있습니다.
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 " )} " ))
)
)
웬 스칼라 3?
2023 년 2 월. 당신이 옳습니다. 우리는 그렇게하기 위해 가장 짧은 달을 선택했습니다 :) 완료!
타임 아웃 예외가 있습니다. 타임 아웃 설정을 어떻게 변경할 수 있습니까?
timeouts
를 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]에서 이메일을 촬영하십시오.
이 라이브러리는 MIT 라이센스의 조건에 따라 오픈 소스로 제공되고 게시됩니다.
이 프로젝트는 오픈 소스이며 모든 기여 또는 피드백을 환영합니다 (여기).
이 도서관의 개발은 -cequence.io- The future of contracting
의해 지원되었습니다.
Peter Banda가 창조하고 유지합니다.