From 1fca7bfdc67553755407863037a681cf4d748784 Mon Sep 17 00:00:00 2001 From: Kai Kreuzer Date: Tue, 17 Oct 2023 12:30:52 +0200 Subject: [PATCH] [chatgpt] Add support for LocalAI and other compatible services (#15385) * Add support for LocalAI and other compatible services -------- Signed-off-by: Kai Kreuzer --- bundles/org.openhab.binding.chatgpt/README.md | 10 +++++++--- .../internal/ChatGPTBindingConstants.java | 3 --- .../internal/ChatGPTConfiguration.java | 2 ++ .../chatgpt/internal/ChatGPTHandler.java | 14 ++++++++----- .../resources/OH-INF/i18n/chatgpt.properties | 10 +++++++--- .../resources/OH-INF/thing/thing-types.xml | 20 +++++++++++++++++++ 6 files changed, 45 insertions(+), 14 deletions(-) diff --git a/bundles/org.openhab.binding.chatgpt/README.md b/bundles/org.openhab.binding.chatgpt/README.md index cf38c9524..d48a07352 100644 --- a/bundles/org.openhab.binding.chatgpt/README.md +++ b/bundles/org.openhab.binding.chatgpt/README.md @@ -14,9 +14,13 @@ The binding supports a single thing type `account`, which corresponds to the Ope The `account` thing requires a single configuration parameter, which is the API key that allows accessing the account. API keys can be created and managed under . -| Name | Type | Description | Default | Required | Advanced | -|-----------------|---------|-----------------------------------------|---------|----------|----------| -| apiKey | text | The API key to be used for the requests | N/A | yes | no | +| Name | Type | Description | Default | Required | Advanced | +|-----------------|---------|-----------------------------------------------------------|--------------------------------------------|----------|----------| +| apiKey | text | The API key to be used for the requests | N/A | yes | no | +| apiUrl | text | The server API where to reach the AI service | https://api.openai.com/v1/chat/completions | no | yes | +| modelUrl | text | The model url where to retrieve the available models from | https://api.openai.com/v1/models | no | yes | + +The advanced parameters `apiUrl` and `modelUrl` can be used, if any other ChatGPT-compatible service is used, e.g. a local installation of [LocalAI](https://github.com/go-skynet/LocalAI). ## Channels diff --git a/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTBindingConstants.java b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTBindingConstants.java index 3d07d6cb6..87635b04c 100644 --- a/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTBindingConstants.java +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTBindingConstants.java @@ -31,7 +31,4 @@ public class ChatGPTBindingConstants { // List of all Channel ids public static final String CHANNEL_CHAT = "chat"; - - public static final String OPENAI_API_URL = "https://api.openai.com/v1/chat/completions"; - public static final String OPENAI_MODELS_URL = "https://api.openai.com/v1/models"; } diff --git a/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTConfiguration.java b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTConfiguration.java index b09b5d806..e2618c4d3 100644 --- a/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTConfiguration.java +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTConfiguration.java @@ -23,4 +23,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault; public class ChatGPTConfiguration { public String apiKey = ""; + public String apiUrl = "https://api.openai.com/v1/chat/completions"; + public String modelUrl = "https://api.openai.com/v1/models"; } diff --git a/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTHandler.java b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTHandler.java index e39b1bc11..e04ee01d0 100644 --- a/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTHandler.java +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTHandler.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.chatgpt.internal; -import static org.openhab.binding.chatgpt.internal.ChatGPTBindingConstants.*; - import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -63,6 +61,9 @@ public class ChatGPTHandler extends BaseThingHandler { private Gson gson = new Gson(); private String apiKey = ""; + private String apiUrl = ""; + private String modelUrl = ""; + private String lastPrompt = ""; private List models = List.of(); @@ -123,7 +124,7 @@ public class ChatGPTHandler extends BaseThingHandler { root.add("messages", messages); String queryJson = gson.toJson(root); - Request request = httpClient.newRequest(OPENAI_API_URL).method(HttpMethod.POST) + Request request = httpClient.newRequest(apiUrl).method(HttpMethod.POST) .header("Content-Type", "application/json").header("Authorization", "Bearer " + apiKey) .content(new StringContentProvider(queryJson)); logger.trace("Query '{}'", queryJson); @@ -158,12 +159,15 @@ public class ChatGPTHandler extends BaseThingHandler { } this.apiKey = apiKey; + this.apiUrl = config.apiUrl; + this.modelUrl = config.modelUrl; + updateStatus(ThingStatus.UNKNOWN); scheduler.execute(() -> { try { - Request request = httpClient.newRequest(OPENAI_MODELS_URL).method(HttpMethod.GET) - .header("Authorization", "Bearer " + apiKey); + Request request = httpClient.newRequest(modelUrl).method(HttpMethod.GET).header("Authorization", + "Bearer " + apiKey); ContentResponse response = request.send(); if (response.getStatus() == 200) { updateStatus(ThingStatus.ONLINE); diff --git a/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/i18n/chatgpt.properties b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/i18n/chatgpt.properties index 48390a3b8..6c96866ec 100644 --- a/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/i18n/chatgpt.properties +++ b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/i18n/chatgpt.properties @@ -12,6 +12,10 @@ thing-type.chatgpt.account.description = Account at OpenAI that is used for acce thing-type.config.chatgpt.account.apiKey.label = API Key thing-type.config.chatgpt.account.apiKey.description = API key to access the account +thing-type.config.chatgpt.account.apiUrl.label = API URL +thing-type.config.chatgpt.account.apiUrl.description = The server API where to reach the AI service. +thing-type.config.chatgpt.account.modelUrl.label = Model URL +thing-type.config.chatgpt.account.modelUrl.description = The model url where to retrieve the available models from. # channel types @@ -29,7 +33,7 @@ channel-type.config.chatgpt.chat.systemMessage.description = The system message channel-type.config.chatgpt.chat.temperature.label = Temperature channel-type.config.chatgpt.chat.temperature.description = Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. -# Status messages +# status messages -offline.configuration-error=No API key configured -offline.communication-error=Could not connect to OpenAI API +offline.configuration-error = No API key configured +offline.communication-error = Could not connect to OpenAI API diff --git a/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/thing/thing-types.xml index 95d2ee7e2..f7aedc576 100644 --- a/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/thing/thing-types.xml @@ -19,6 +19,26 @@ API key to access the account + + + The server API where to reach the AI service. + https://api.openai.com/v1/chat/completions + true + + + + false + + + + The model url where to retrieve the available models from. + https://api.openai.com/v1/models + true + + + + false +