You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kyuubi.apache.org by ch...@apache.org on 2023/03/17 13:49:09 UTC

[kyuubi] branch master updated: [KYUUBI #4548] Kyuubi Chat Engine supports Chinese questions and HTTP proxy

This is an automated email from the ASF dual-hosted git repository.

chengpan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kyuubi.git


The following commit(s) were added to refs/heads/master by this push:
     new 6ded07974 [KYUUBI #4548] Kyuubi Chat Engine supports Chinese questions and HTTP proxy
6ded07974 is described below

commit 6ded07974eebcbd8cbba4167a25c80e4549014d6
Author: sychen <sy...@ctrip.com>
AuthorDate: Fri Mar 17 21:48:58 2023 +0800

    [KYUUBI #4548] Kyuubi Chat Engine supports Chinese questions and HTTP proxy
    
    ### _Why are the changes needed?_
    
    - Support Chinese question
    - Support proxy settings
    - Support setting timeout
    
    <img width="1228" alt="image" src="https://user-images.githubusercontent.com/3898450/225851246-8762a451-9743-4c1d-8a33-cc49a926dfec.png">
    
    ### _How was this patch tested?_
    - [ ] Add some test cases that check the changes thoroughly including negative and positive cases if possible
    
    - [x] Add screenshots for manual tests if appropriate
    
    - [x] [Run test](https://kyuubi.readthedocs.io/en/master/develop_tools/testing.html#running-tests) locally before make a pull request
    
    Closes #4548 from cxzl25/chatgpt_followup.
    
    Closes #4548
    
    1d5715442 [Cheng Pan] Update externals/kyuubi-chat-engine/src/main/scala/org/apache/kyuubi/engine/chat/provider/ChatGPTProvider.scala
    7add6a733 [Cheng Pan] Update externals/kyuubi-chat-engine/src/main/scala/org/apache/kyuubi/engine/chat/provider/ChatGPTProvider.scala
    55974f298 [sychen] fix
    2d360e102 [sychen] typo
    19b5d0814 [sychen] doc
    bdf8e29b6 [sychen] 1.utf8;2.proxy;timeout
    
    Lead-authored-by: sychen <sy...@ctrip.com>
    Co-authored-by: Cheng Pan <pa...@gmail.com>
    Signed-off-by: Cheng Pan <ch...@apache.org>
---
 docs/deployment/settings.md                        |  3 ++
 .../engine/chat/provider/ChatGPTProvider.scala     | 33 ++++++++++++++++------
 .../org/apache/kyuubi/config/KyuubiConf.scala      | 25 ++++++++++++++++
 3 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/docs/deployment/settings.md b/docs/deployment/settings.md
index 9c5f76712..db6e3d246 100644
--- a/docs/deployment/settings.md
+++ b/docs/deployment/settings.md
@@ -122,6 +122,9 @@ You can configure the Kyuubi properties in `$KYUUBI_HOME/conf/kyuubi-defaults.co
 |----------------------------------------------------------|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [...]
 | kyuubi.engine.chat.extra.classpath                       | &lt;undefined&gt;         | The extra classpath for the Chat engine, for configuring the location of the SDK and etc.                                                                                                                                                                                                                                                                                                                           [...]
 | kyuubi.engine.chat.gpt.apiKey                            | &lt;undefined&gt;         | The key to access OpenAI open API, which could be got at https://platform.openai.com/account/api-keys                                                                                                                                                                                                                                                                                                               [...]
+| kyuubi.engine.chat.gpt.http.connect.timeout              | PT2M                      | The timeout[ms] for establishing the connection with the Chat GPT server. A timeout value of zero is interpreted as an infinite timeout.                                                                                                                                                                                                                                                                            [...]
+| kyuubi.engine.chat.gpt.http.proxy                        | &lt;undefined&gt;         | HTTP proxy url for API calling in Chat GPT engine. e.g. http://127.0.0.1:1087                                                                                                                                                                                                                                                                                                                                       [...]
+| kyuubi.engine.chat.gpt.http.socket.timeout               | PT2M                      | The timeout[ms] for waiting for data packets after Chat GPT server connection is established. A timeout value of zero is interpreted as an infinite timeout.                                                                                                                                                                                                                                                        [...]
 | kyuubi.engine.chat.java.options                          | &lt;undefined&gt;         | The extra Java options for the Chat engine                                                                                                                                                                                                                                                                                                                                                                          [...]
 | kyuubi.engine.chat.memory                                | 1g                        | The heap memory for the Chat engine                                                                                                                                                                                                                                                                                                                                                                                 [...]
 | kyuubi.engine.chat.provider                              | ECHO                      | The provider for the Chat engine. Candidates: <ul> <li>ECHO: simply replies a welcome message.</li> <li>GPT: a.k.a ChatGPT, powered by OpenAI.</li></ul>                                                                                                                                                                                                                                                            [...]
diff --git a/externals/kyuubi-chat-engine/src/main/scala/org/apache/kyuubi/engine/chat/provider/ChatGPTProvider.scala b/externals/kyuubi-chat-engine/src/main/scala/org/apache/kyuubi/engine/chat/provider/ChatGPTProvider.scala
index f948eb154..28ef36bb4 100644
--- a/externals/kyuubi-chat-engine/src/main/scala/org/apache/kyuubi/engine/chat/provider/ChatGPTProvider.scala
+++ b/externals/kyuubi-chat-engine/src/main/scala/org/apache/kyuubi/engine/chat/provider/ChatGPTProvider.scala
@@ -21,9 +21,10 @@ import java.util
 import java.util.concurrent.TimeUnit
 
 import com.google.common.cache.{CacheBuilder, CacheLoader, LoadingCache}
-import org.apache.http.HttpStatus
+import org.apache.http.{HttpHost, HttpStatus}
+import org.apache.http.client.config.RequestConfig
 import org.apache.http.client.methods.HttpPost
-import org.apache.http.entity.StringEntity
+import org.apache.http.entity.{ContentType, StringEntity}
 import org.apache.http.impl.client.{CloseableHttpClient, HttpClientBuilder}
 import org.apache.http.util.EntityUtils
 
@@ -32,9 +33,25 @@ import org.apache.kyuubi.engine.chat.provider.ChatProvider.mapper
 
 class ChatGPTProvider(conf: KyuubiConf) extends ChatProvider {
 
-  val token = conf.get(KyuubiConf.ENGINE_CHAT_GPT_API_KEY).get
+  private val gptApiKey = conf.get(KyuubiConf.ENGINE_CHAT_GPT_API_KEY).getOrElse {
+    throw new IllegalArgumentException(
+      s"'${KyuubiConf.ENGINE_CHAT_GPT_API_KEY.key}' must be configured, " +
+        s"which could be got at https://platform.openai.com/account/api-keys")
+  }
 
-  val httpClient: CloseableHttpClient = HttpClientBuilder.create().build()
+  private val httpClient: CloseableHttpClient = HttpClientBuilder.create().build()
+
+  private val requestConfig = {
+    val connectTimeout = conf.get(KyuubiConf.ENGINE_CHAT_GPT_HTTP_CONNECT_TIMEOUT).asInstanceOf[Int]
+    val socketTimeout = conf.get(KyuubiConf.ENGINE_CHAT_GPT_HTTP_SOCKET_TIMEOUT).asInstanceOf[Int]
+    val builder: RequestConfig.Builder = RequestConfig.custom()
+      .setConnectTimeout(connectTimeout)
+      .setSocketTimeout(socketTimeout)
+    conf.get(KyuubiConf.ENGINE_CHAT_GPT_HTTP_PROXY).foreach { url =>
+      builder.setProxy(HttpHost.create(url))
+    }
+    builder.build()
+  }
 
   private val chatHistory: LoadingCache[String, util.ArrayDeque[Message]] =
     CacheBuilder.newBuilder()
@@ -53,8 +70,7 @@ class ChatGPTProvider(conf: KyuubiConf) extends ChatProvider {
     messages.addLast(Message("user", q))
 
     val request = new HttpPost("https://api.openai.com/v1/chat/completions")
-    request.addHeader("Content-Type", "application/json")
-    request.addHeader("Authorization", "Bearer " + token)
+    request.addHeader("Authorization", "Bearer " + gptApiKey)
 
     val req = Map(
       "messages" -> messages,
@@ -62,8 +78,9 @@ class ChatGPTProvider(conf: KyuubiConf) extends ChatProvider {
       "max_tokens" -> 200,
       "temperature" -> 0.5,
       "top_p" -> 1)
-
-    request.setEntity(new StringEntity(mapper.writeValueAsString(req)))
+    val entity = new StringEntity(mapper.writeValueAsString(req), ContentType.APPLICATION_JSON)
+    request.setEntity(entity)
+    request.setConfig(requestConfig)
     val responseEntity = httpClient.execute(request)
     val respJson = mapper.readTree(EntityUtils.toString(responseEntity.getEntity))
     val statusCode = responseEntity.getStatusLine.getStatusCode
diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala
index b39bee307..35626eea5 100644
--- a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala
+++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala
@@ -2667,6 +2667,31 @@ object KyuubiConf {
       .stringConf
       .createOptional
 
+  val ENGINE_CHAT_GPT_HTTP_PROXY: OptionalConfigEntry[String] =
+    buildConf("kyuubi.engine.chat.gpt.http.proxy")
+      .doc("HTTP proxy url for API calling in Chat GPT engine. e.g. http://127.0.0.1:1087")
+      .version("1.8.0")
+      .stringConf
+      .createOptional
+
+  val ENGINE_CHAT_GPT_HTTP_CONNECT_TIMEOUT: ConfigEntry[Long] =
+    buildConf("kyuubi.engine.chat.gpt.http.connect.timeout")
+      .doc("The timeout[ms] for establishing the connection with the Chat GPT server. " +
+        "A timeout value of zero is interpreted as an infinite timeout.")
+      .version("1.8.0")
+      .timeConf
+      .checkValue(_ >= 0, "must be 0 or positive number")
+      .createWithDefault(Duration.ofSeconds(120).toMillis)
+
+  val ENGINE_CHAT_GPT_HTTP_SOCKET_TIMEOUT: ConfigEntry[Long] =
+    buildConf("kyuubi.engine.chat.gpt.http.socket.timeout")
+      .doc("The timeout[ms] for waiting for data packets after Chat GPT server " +
+        "connection is established. A timeout value of zero is interpreted as an infinite timeout.")
+      .version("1.8.0")
+      .timeConf
+      .checkValue(_ >= 0, "must be 0 or positive number")
+      .createWithDefault(Duration.ofSeconds(120).toMillis)
+
   val ENGINE_JDBC_MEMORY: ConfigEntry[String] =
     buildConf("kyuubi.engine.jdbc.memory")
       .doc("The heap memory for the JDBC query engine")