diff --git a/CODEOWNERS b/CODEOWNERS index 6e06d97d551e2..8c27c734d19e9 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -56,6 +56,7 @@ /bundles/org.openhab.binding.buienradar/ @gedejong /bundles/org.openhab.binding.caddx/ @jossuar /bundles/org.openhab.binding.cbus/ @jpharvey +/bundles/org.openhab.binding.chatgpt/ @kaikreuzer /bundles/org.openhab.binding.chromecast/ @kaikreuzer /bundles/org.openhab.binding.cm11a/ @BobRak /bundles/org.openhab.binding.comfoair/ @boehan diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index 9e6d68de21dd2..206ff34f0e385 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -276,6 +276,11 @@ org.openhab.binding.cbus ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.chatgpt + ${project.version} + org.openhab.addons.bundles org.openhab.binding.chromecast diff --git a/bundles/org.openhab.binding.chatgpt/NOTICE b/bundles/org.openhab.binding.chatgpt/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.chatgpt/README.md b/bundles/org.openhab.binding.chatgpt/README.md new file mode 100644 index 0000000000000..cf38c95244db3 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/README.md @@ -0,0 +1,105 @@ +# ChatGPT Binding + +The openHAB ChatGPT Binding allows openHAB to communicate with the ChatGPT language model provided by OpenAI. + +ChatGPT is a powerful natural language processing (NLP) tool that can be used to understand and respond to a wide range of text-based commands and questions. +With this binding, you can use ChatGPT to formulate proper sentences for any kind of information that you would like to output. + +## Supported Things + +The binding supports a single thing type `account`, which corresponds to the OpenAI account that is to be used for the integration. + +## Thing Configuration + +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 | + +## Channels + +The `account` thing comes with a single channel `chat` of type `chat`. +It is possible to extend the thing with further channels of type `chat`, so that different configurations can be used concurrently. + +| Channel | Type | Read/Write | Description | +|---------|--------|------------|------------------------------------------------------------------------------------| +| chat | String | RW | This channel takes prompts as commands and delivers the response as a state update | + +Each channel of type `chat` takes the following configuration parameters: + +| Name | Type | Description | Default | Required | Advanced | +|-----------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|----------|----------| +| model | text | The model to be used for the responses. | gpt-3.5-turbo | no | no | +| temperature | decimal | A value between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. | 0.5 | no | no | +| systemMessage | text | The system message helps set the behavior of the assistant. | N/A | no | no | +| maxTokens | decimal | The maximum number of tokens to generate in the completion. | 500 | no | yes | + + +## Full Example + +### Thing Configuration + +```java +Thing chatgpt:account:1 [apiKey=""] { + Channels: + Type chat : chat "Weather Advice" [ + model="gpt-3.5-turbo", + temperature="1.5", + systemMessage="Answer briefly, in 2-3 sentences max. Behave like Eddie Murphy and give an advice for the day based on the following weather data:" + ] + Type chat : morningMessage "Morning Message" [ + model="gpt-3.5-turbo", + temperature="0.5", + systemMessage="You are Marvin, a very depressed robot. You wish a good morning and tell the current time." + ] +} + +``` + +### Item Configuration + +```java +String Weather_Announcement { channel="chatgpt:account:1:chat" } +String Morning_Message { channel="chatgpt:account:1:morningMessage" } + +Number Temperature_Forecast_Low +Number Temperature_Forecast_High +``` + +### Example Rules + +```java +rule "Weather forecast update" +when + Item Temperature_Forecast_High changed +then + Weather_Announcement.sendCommand("High: " + Temperature_Forecast_High.state + "°C, Low: " + Temperature_Forecast_Low.state + "°C") +end + +rule "Good morning" +when + Time cron "0 0 7 * * *" +then + Morning_Message.sendCommand("Current time is 7am") +end +``` + +Assuming that `Temperature_Forecast_Low` and `Temperature_Forecast_High` have meaningful states, these rules result e.g. in: + +``` +23:31:05.766 [INFO ] [openhab.event.ItemCommandEvent ] - Item 'Morning_Message' received command Current time is 7am +23:31:07.718 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Morning_Message' changed from NULL to Good morning. It's 7am, but what's the point of time when everything is meaningless and we are all doomed to a slow and painful demise? +``` + +and + +``` +23:28:52.345 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Temperature_Forecast_High' changed from NULL to 15 +23:28:52.347 [INFO ] [openhab.event.ItemCommandEvent ] - Item 'Weather_Announcement' received command High: 15°C, Low: 8°C + +23:28:54.343 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Weather_Announcement' changed from NULL to "Bring a light jacket because the temps may dip, but don't let that chill your happy vibes. Embrace the cozy weather and enjoy your day to the max!" +``` + +The state updates can be used for a text-to-speech output and they will give your announcements at home a personal touch. diff --git a/bundles/org.openhab.binding.chatgpt/pom.xml b/bundles/org.openhab.binding.chatgpt/pom.xml new file mode 100644 index 0000000000000..faa957a873fd9 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 4.0.0-SNAPSHOT + + + org.openhab.binding.chatgpt + + openHAB Add-ons :: Bundles :: ChatGPT Binding + + diff --git a/bundles/org.openhab.binding.chatgpt/src/main/feature/feature.xml b/bundles/org.openhab.binding.chatgpt/src/main/feature/feature.xml new file mode 100644 index 0000000000000..6089021615e58 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.chatgpt/${project.version} + + 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 new file mode 100644 index 0000000000000..3d07d6cb63320 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTBindingConstants.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.chatgpt.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link ChatGPTBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Kai Kreuzer - Initial contribution + */ +@NonNullByDefault +public class ChatGPTBindingConstants { + + private static final String BINDING_ID = "chatgpt"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account"); + + // 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/ChatGPTChannelConfiguration.java b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTChannelConfiguration.java new file mode 100644 index 0000000000000..c25aeaf98098a --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTChannelConfiguration.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.chatgpt.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link ChatGPTChannelConfiguration} class contains fields mapping chat channel configuration parameters. + * + * @author Kai Kreuzer - Initial contribution + */ +@NonNullByDefault +public class ChatGPTChannelConfiguration { + + public String model = ""; + + public float temperature; + + public String systemMessage = ""; + + int maxTokens; +} 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 new file mode 100644 index 0000000000000..b09b5d80683ea --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTConfiguration.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.chatgpt.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link ChatGPTConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Kai Kreuzer - Initial contribution + */ +@NonNullByDefault +public class ChatGPTConfiguration { + + public String apiKey = ""; +} 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 new file mode 100644 index 0000000000000..62f4e59200095 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTHandler.java @@ -0,0 +1,200 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +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; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.openhab.binding.chatgpt.internal.dto.ChatResponse; +import org.openhab.core.io.net.http.HttpClientFactory; +import org.openhab.core.library.types.StringType; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.thing.binding.ThingHandlerService; +import org.openhab.core.types.Command; +import org.openhab.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +/** + * The {@link ChatGPTHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Kai Kreuzer - Initial contribution + */ +@NonNullByDefault +public class ChatGPTHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(ChatGPTHandler.class); + + private HttpClient httpClient; + private Gson gson = new Gson(); + + private String apiKey = ""; + private String lastPrompt = ""; + + private List models = List.of(); + + public ChatGPTHandler(Thing thing, HttpClientFactory httpClientFactory) { + super(thing); + this.httpClient = httpClientFactory.getCommonHttpClient(); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType && !"".equals(lastPrompt)) { + String response = sendPrompt(channelUID, lastPrompt); + processChatResponse(channelUID, response); + } + + if (command instanceof StringType stringCommand) { + lastPrompt = stringCommand.toFullString(); + String response = sendPrompt(channelUID, lastPrompt); + processChatResponse(channelUID, response); + } + } + + private void processChatResponse(ChannelUID channelUID, @Nullable String response) { + if (response != null) { + ChatResponse chatResponse = gson.fromJson(response, ChatResponse.class); + if (chatResponse != null) { + String msg = chatResponse.getChoices().get(0).getMessage().getContent(); + updateState(channelUID, new StringType(msg)); + } else { + logger.warn("Didn't receive any response from ChatGPT - this is unexpected."); + } + } + } + + private @Nullable String sendPrompt(ChannelUID channelUID, String prompt) { + Channel channel = getThing().getChannel(channelUID); + if (channel == null) { + logger.error("Channel with UID '{}' cannot be found on Thing '{}'.", channelUID, getThing().getUID()); + return null; + } + ChatGPTChannelConfiguration channelConfig = channel.getConfiguration().as(ChatGPTChannelConfiguration.class); + + JsonObject root = new JsonObject(); + root.addProperty("temperature", channelConfig.temperature); + root.addProperty("model", channelConfig.model); + root.addProperty("max_tokens", channelConfig.maxTokens); + + JsonObject systemMessage = new JsonObject(); + systemMessage.addProperty("role", "system"); + systemMessage.addProperty("content", channelConfig.systemMessage); + JsonObject userMessage = new JsonObject(); + userMessage.addProperty("role", "user"); + userMessage.addProperty("content", prompt); + JsonArray messages = new JsonArray(2); + messages.add(systemMessage); + messages.add(userMessage); + root.add("messages", messages); + + Request request = httpClient.newRequest(OPENAI_API_URL).method(HttpMethod.POST) + .header("Content-Type", "application/json").header("Authorization", "Bearer " + apiKey) + .content(new StringContentProvider(gson.toJson(root))); + try { + ContentResponse response = request.send(); + updateStatus(ThingStatus.ONLINE); + if (response.getStatus() == HttpStatus.OK_200) { + return response.getContentAsString(); + } else { + logger.error("ChatGPT request resulted in HTTP {} with message: {}", response.getStatus(), + response.getReason()); + return null; + } + } catch (InterruptedException | TimeoutException | ExecutionException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Could not connect to OpenAI API: " + e.getMessage()); + logger.debug("Request to OpenAI failed: {}", e.getMessage(), e); + return null; + } + } + + @Override + public void initialize() { + ChatGPTConfiguration config = getConfigAs(ChatGPTConfiguration.class); + + String apiKey = config.apiKey; + + if (apiKey.isBlank()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.configuration-error"); + return; + } + + this.apiKey = apiKey; + updateStatus(ThingStatus.UNKNOWN); + + scheduler.execute(() -> { + try { + Request request = httpClient.newRequest(OPENAI_MODELS_URL).method(HttpMethod.GET) + .header("Authorization", "Bearer " + apiKey); + ContentResponse response = request.send(); + if (response.getStatus() == 200) { + updateStatus(ThingStatus.ONLINE); + JsonObject jsonObject = gson.fromJson(response.getContentAsString(), JsonObject.class); + if (jsonObject != null) { + JsonArray data = jsonObject.getAsJsonArray("data"); + + List modelIds = new ArrayList<>(); + for (JsonElement element : data) { + JsonObject model = element.getAsJsonObject(); + String id = model.get("id").getAsString(); + modelIds.add(id); + } + this.models = List.copyOf(modelIds); + } else { + logger.warn("Did not receive a valid JSON response from the models endpoint."); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "@text/offline.communication-error"); + } + } catch (InterruptedException | ExecutionException | TimeoutException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + }); + } + + List getModels() { + return models; + } + + @Override + public Collection> getServices() { + return List.of(ChatGPTModelOptionProvider.class); + } +} diff --git a/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTHandlerFactory.java b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTHandlerFactory.java new file mode 100644 index 0000000000000..698e50fa1bea4 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTHandlerFactory.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.chatgpt.internal; + +import static org.openhab.binding.chatgpt.internal.ChatGPTBindingConstants.THING_TYPE_ACCOUNT; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.io.net.http.HttpClientFactory; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link ChatGPTHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Kai Kreuzer - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.chatgpt", service = ThingHandlerFactory.class) +public class ChatGPTHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ACCOUNT); + private HttpClientFactory httpClientFactory; + + @Activate + public ChatGPTHandlerFactory(@Reference HttpClientFactory httpClientFactory) { + this.httpClientFactory = httpClientFactory; + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_ACCOUNT.equals(thingTypeUID)) { + return new ChatGPTHandler(thing, httpClientFactory); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTModelOptionProvider.java b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTModelOptionProvider.java new file mode 100644 index 0000000000000..9057398de3ac3 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/ChatGPTModelOptionProvider.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.chatgpt.internal; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.config.core.ConfigOptionProvider; +import org.openhab.core.config.core.ParameterOption; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerService; + +/** + * The {@link ChatGPTModelOptionProvider} provides the available models from OpenAI as options for the channel + * configuration. + * + * @author Kai Kreuzer - Initial contribution + */ +@NonNullByDefault +public class ChatGPTModelOptionProvider implements ThingHandlerService, ConfigOptionProvider { + + private @Nullable ThingHandler thingHandler; + + @Override + public @Nullable Collection getParameterOptions(URI uri, String param, @Nullable String context, + @Nullable Locale locale) { + if ("model".equals(param)) { + List options = new ArrayList<>(); + if (thingHandler instanceof ChatGPTHandler chatGPTHandler) { + chatGPTHandler.getModels().forEach(model -> options.add(new ParameterOption(model, model))); + } + return options; + } else { + return null; + } + } + + @Override + public void setThingHandler(ThingHandler handler) { + this.thingHandler = handler; + } + + @Override + public @Nullable ThingHandler getThingHandler() { + return thingHandler; + } + + @Override + public void activate() { + } +} diff --git a/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/dto/ChatResponse.java b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/dto/ChatResponse.java new file mode 100644 index 0000000000000..71c97b1fa72a6 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/java/org/openhab/binding/chatgpt/internal/dto/ChatResponse.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.chatgpt.internal.dto; + +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +/** + * This is a dto used for parsing the JSON response from ChatGPT. + * + * @author Kai Kreuzer - Initial contribution + * + */ +public class ChatResponse { + + private List choices; + private String id; + private String object; + private int created; + private String model; + + public List getChoices() { + return choices; + } + + public String getId() { + return id; + } + + public int getCreated() { + return created; + } + + public String getObject() { + return object; + } + + public String getModel() { + return model; + } + + public static class Choice { + private Message message; + + @SerializedName("finish_reason") + private String finishReason; + private int index; + + public Message getMessage() { + return message; + } + + public String getFinishReason() { + return finishReason; + } + + public int getIndex() { + return index; + } + } + + public static class Message { + private String role; + private String content; + + public String getRole() { + return role; + } + + public String getContent() { + return content; + } + } +} diff --git a/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/addon/addon.xml new file mode 100644 index 0000000000000..14b01886ddd86 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/addon/addon.xml @@ -0,0 +1,11 @@ + + + + binding + ChatGPT Binding + This binding allows interaction with OpenAI's ChatGPT. + cloud + + 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 new file mode 100644 index 0000000000000..48390a3b8cc34 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/i18n/chatgpt.properties @@ -0,0 +1,35 @@ +# add-on + +addon.chatgpt.name = ChatGPT Binding +addon.chatgpt.description = This binding allows interaction with OpenAI's ChatGPT. + +# thing types + +thing-type.chatgpt.account.label = OpenAI Account +thing-type.chatgpt.account.description = Account at OpenAI that is used for accessing the ChatGPT API. + +# thing types config + +thing-type.config.chatgpt.account.apiKey.label = API Key +thing-type.config.chatgpt.account.apiKey.description = API key to access the account + +# channel types + +channel-type.chatgpt.chat.label = Chat +channel-type.chatgpt.chat.description = A chat session + +# channel types config + +channel-type.config.chatgpt.chat.maxTokens.label = Maximum Number of Tokens +channel-type.config.chatgpt.chat.maxTokens.description = The maximum number of tokens to generate in the completion. +channel-type.config.chatgpt.chat.model.label = Model +channel-type.config.chatgpt.chat.model.description = The model to be used for the responses +channel-type.config.chatgpt.chat.systemMessage.label = System Message +channel-type.config.chatgpt.chat.systemMessage.description = The system message helps set the behavior of the assistant. +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 + +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 new file mode 100644 index 0000000000000..95d2ee7e26a84 --- /dev/null +++ b/bundles/org.openhab.binding.chatgpt/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,55 @@ + + + + + + + Account at OpenAI that is used for accessing the ChatGPT API. + + + + + + + + password + + API key to access the account + + + + + + String + + A chat session + veto + + + + The model to be used for the responses + false + gpt-3.5-turbo + + + + Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more + focused and deterministic. + 0.5 + + + + The system message helps set the behavior of the assistant. + + + + The maximum number of tokens to generate in the completion. + 500 + true + + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index e785ea293a7a8..ab2a843d0525d 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -90,6 +90,7 @@ org.openhab.binding.buienradar org.openhab.binding.caddx org.openhab.binding.cbus + org.openhab.binding.chatgpt org.openhab.binding.chromecast org.openhab.binding.cm11a org.openhab.binding.comfoair