Skip to content

Commit be93f67

Browse files
authored
Merge pull request #66 from cequence-io/feature/refactor-out-ws-client
Feature/refactor out ws client
2 parents 791ae1d + 00f0c28 commit be93f67

File tree

117 files changed

+1291
-1315
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+1291
-1315
lines changed

.scalafmt.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ newlines {
1313
implicitParamListModifierForce = [before]
1414
}
1515

16+
//rewrite {
17+
// trailingCommas.style = always
18+
//}
19+
1620
verticalMultiline {
1721
atDefnSite = true
1822
arityThreshold = 2

anthropic-client/build.sbt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import Dependencies.Versions._
2+
13
name := "openai-scala-anthropic-client"
24

35
description := "Scala client for Anthropic API implemented using Play WS lib."
6+
7+
libraryDependencies += "org.scalactic" %% "scalactic" % "3.2.18"
8+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.18" % Test
9+
libraryDependencies += "org.scalamock" %% "scalamock" % scakaMock % Test

anthropic-client/src/main/scala/io/cequence/openaiscala/anthropic/JsonFormats.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.cequence.openaiscala.anthropic
22

3-
import io.cequence.openaiscala.JsonUtil
3+
import io.cequence.wsclient.JsonUtil
44
import io.cequence.openaiscala.anthropic.domain.Content.ContentBlock.{ImageBlock, TextBlock}
55
import io.cequence.openaiscala.anthropic.domain.Content.{
66
ContentBlock,

anthropic-client/src/main/scala/io/cequence/openaiscala/anthropic/domain/ChatRole.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.cequence.openaiscala.anthropic.domain
22

3-
import io.cequence.openaiscala.domain.EnumValue
3+
import io.cequence.wsclient.domain.EnumValue
44

55
sealed trait ChatRole extends EnumValue {
66
override def toString: String = super.toString.toLowerCase

anthropic-client/src/main/scala/io/cequence/openaiscala/anthropic/domain/response/CreateMessageResponse.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package io.cequence.openaiscala.anthropic.domain.response
33
import io.cequence.openaiscala.anthropic.domain.ChatRole
44
import io.cequence.openaiscala.anthropic.domain.Content.ContentBlocks
55
import io.cequence.openaiscala.anthropic.domain.response.CreateMessageResponse.UsageInfo
6-
import io.cequence.openaiscala.domain.NamedEnumValue
6+
import io.cequence.wsclient.domain.NamedEnumValue
77

88
final case class CreateMessageResponse(
99
id: String,
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package io.cequence.openaiscala.anthropic.service
2+
3+
import io.cequence.wsclient.domain.CequenceWSException
4+
5+
class AnthropicScalaClientException(
6+
message: String,
7+
cause: Throwable
8+
) extends CequenceWSException(message, cause) {
9+
def this(message: String) = this(message, null)
10+
}
11+
12+
class AnthropicScalaClientTimeoutException(
13+
message: String,
14+
cause: Throwable
15+
) extends AnthropicScalaClientException(message, cause) {
16+
def this(message: String) = this(message, null)
17+
}
18+
19+
class AnthropicScalaClientUnknownHostException(
20+
message: String,
21+
cause: Throwable
22+
) extends AnthropicScalaClientException(message, cause) {
23+
def this(message: String) = this(message, null)
24+
}
25+
26+
class AnthropicScalaTokenCountExceededException(
27+
message: String,
28+
cause: Throwable
29+
) extends AnthropicScalaClientException(message, cause) {
30+
def this(message: String) = this(message, null)
31+
}
32+
33+
class AnthropicScalaUnauthorizedException(
34+
message: String,
35+
cause: Throwable
36+
) extends AnthropicScalaClientException(message, cause) {
37+
def this(message: String) = this(message, null)
38+
}
39+
40+
class AnthropicScalaNotFoundException(
41+
message: String,
42+
cause: Throwable
43+
) extends AnthropicScalaClientException(message, cause) {
44+
def this(message: String) = this(message, null)
45+
}
46+
47+
class AnthropicScalaRateLimitException(
48+
message: String,
49+
cause: Throwable
50+
) extends AnthropicScalaClientException(message, cause) {
51+
def this(message: String) = this(message, null)
52+
}
53+
54+
class AnthropicScalaServerErrorException(
55+
message: String,
56+
cause: Throwable
57+
) extends AnthropicScalaClientException(message, cause) {
58+
def this(message: String) = this(message, null)
59+
}
60+
61+
class AnthropicScalaEngineOverloadedException(
62+
message: String,
63+
cause: Throwable
64+
) extends AnthropicScalaClientException(message, cause) {
65+
def this(message: String) = this(message, null)
66+
}

anthropic-client/src/main/scala/io/cequence/openaiscala/anthropic/service/AnthropicService.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import io.cequence.openaiscala.anthropic.domain.response.{
88
CreateMessageResponse
99
}
1010
import io.cequence.openaiscala.anthropic.domain.settings.AnthropicCreateMessageSettings
11-
import io.cequence.openaiscala.service.CloseableService
11+
import io.cequence.wsclient.service.CloseableService
1212

1313
import scala.concurrent.Future
1414

anthropic-client/src/main/scala/io/cequence/openaiscala/anthropic/service/AnthropicServiceFactory.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import io.cequence.openaiscala.anthropic.service.impl.{
55
AnthropicServiceImpl,
66
OpenAIAnthropicChatCompletionService
77
}
8-
import io.cequence.openaiscala.service.OpenAIChatCompletionService
98
import io.cequence.openaiscala.service.StreamedServiceTypes.OpenAIChatCompletionStreamedService
10-
import io.cequence.openaiscala.service.ws.Timeouts
9+
import io.cequence.wsclient.domain.WsRequestContext
10+
import io.cequence.wsclient.service.ws.Timeouts
1111

1212
import scala.concurrent.ExecutionContext
1313

@@ -17,8 +17,8 @@ import scala.concurrent.ExecutionContext
1717
*/
1818
object AnthropicServiceFactory extends AnthropicServiceConsts {
1919

20-
private val apiVersion = "2023-06-01"
21-
private val envAPIKey = "ANTHROPIC_API_KEY"
20+
private def apiVersion = "2023-06-01"
21+
private def envAPIKey = "ANTHROPIC_API_KEY"
2222

2323
/**
2424
* Create a new instance of the [[OpenAIChatCompletionService]] wrapping the AnthropicService
@@ -84,6 +84,7 @@ object AnthropicServiceFactory extends AnthropicServiceConsts {
8484
implicit val ec: ExecutionContext,
8585
val materializer: Materializer
8686
) extends AnthropicServiceImpl {
87-
override protected val extraParams: Seq[(String, String)] = Nil
87+
override protected val requestContext: WsRequestContext =
88+
WsRequestContext(authHeaders = authHeaders, explTimeouts = explTimeouts)
8889
}
8990
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package io.cequence.openaiscala.anthropic.service
2+
3+
import io.cequence.openaiscala._
4+
import io.cequence.wsclient.service.ws.WSRequestHelper
5+
6+
/**
7+
* Handle error codes for the Anthropic service.
8+
*
9+
* @since March
10+
* 2024
11+
*/
12+
trait HandleAnthropicErrorCodes extends WSRequestHelper {
13+
14+
override protected def handleErrorCodes(
15+
httpCode: Int,
16+
message: String
17+
): Nothing = {
18+
val errorMessage = s"Code ${httpCode} : ${message}"
19+
httpCode match {
20+
21+
// 401 - authentication_error: There’s an issue with your API key.
22+
case 401 => throw new AnthropicScalaUnauthorizedException(errorMessage)
23+
24+
// 403 - permission_error: Your API key does not have permission to use the specified resource.
25+
case 403 => throw new AnthropicScalaUnauthorizedException(errorMessage)
26+
27+
// 404 - not_found_error: The requested resource was not found.
28+
case 404 => throw new AnthropicScalaNotFoundException(errorMessage)
29+
30+
// 429 - rate_limit_error: Your account has hit a rate limit.
31+
case 429 => throw new AnthropicScalaRateLimitException(errorMessage)
32+
33+
// 500 - api_error: An unexpected error has occurred internal to Anthropic’s systems.
34+
case 500 => throw new AnthropicScalaServerErrorException(errorMessage)
35+
36+
// 529 - overloaded_error: Anthropic’s API is temporarily overloaded.
37+
case 529 => throw new AnthropicScalaEngineOverloadedException(errorMessage)
38+
39+
// 400 - invalid_request_error: There was an issue with the format or content of your request. We may also use this error type for other 4XX status codes not listed below.
40+
case 400 => throw new AnthropicScalaClientException(errorMessage)
41+
42+
case _ => throw new AnthropicScalaClientException(errorMessage)
43+
}
44+
}
45+
}

anthropic-client/src/main/scala/io/cequence/openaiscala/anthropic/service/impl/AnthropicServiceImpl.scala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package io.cequence.openaiscala.anthropic.service.impl
22

33
import akka.NotUsed
44
import akka.stream.scaladsl.Source
5-
import io.cequence.openaiscala.JsonUtil.JsonOps
65
import io.cequence.openaiscala.OpenAIScalaClientException
76
import io.cequence.openaiscala.anthropic.JsonFormats
87
import io.cequence.openaiscala.anthropic.domain.response.{
@@ -11,20 +10,21 @@ import io.cequence.openaiscala.anthropic.domain.response.{
1110
}
1211
import io.cequence.openaiscala.anthropic.domain.settings.AnthropicCreateMessageSettings
1312
import io.cequence.openaiscala.anthropic.domain.{ChatRole, Message}
14-
import io.cequence.openaiscala.anthropic.service.AnthropicService
15-
import io.cequence.openaiscala.service.OpenAIWSRequestHelper
16-
import io.cequence.openaiscala.service.impl.OpenAIWSStreamRequestHelper
13+
import io.cequence.openaiscala.anthropic.service.{AnthropicService, HandleAnthropicErrorCodes}
14+
import io.cequence.wsclient.JsonUtil.JsonOps
15+
import io.cequence.wsclient.service.ws.stream.WSStreamRequestHelper
1716
import play.api.libs.json.{JsValue, Json}
1817

1918
import scala.concurrent.Future
2019

21-
// TODO: Introduce Anthropic specific exception and handle error codes
22-
// Shouldn't use OpenAIWSRequestHelper and OpenAIWSStreamRequestHelper
23-
private[service] trait AnthropicServiceImpl
20+
trait Anthropic
2421
extends AnthropicService
25-
with OpenAIWSRequestHelper
26-
with OpenAIWSStreamRequestHelper
27-
with JsonFormats {
22+
with WSStreamRequestHelper
23+
with HandleAnthropicErrorCodes
24+
with JsonFormats
25+
26+
// Shouldn't use OpenAIWSRequestHelper and OpenAIWSStreamRequestHelper
27+
private[service] trait AnthropicServiceImpl extends Anthropic {
2828

2929
override protected type PEP = EndPoint
3030
override protected type PT = Param

0 commit comments

Comments
 (0)