[chatgpt] Initial contribution of the ChatGPT binding (#14809)

* Initial contribution of the ChatGPT binding

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer 2023-04-21 12:09:53 +02:00 committed by GitHub
parent bf979a4548
commit bb10740d3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 762 additions and 0 deletions

View File

@ -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

View File

@ -276,6 +276,11 @@
<artifactId>org.openhab.binding.cbus</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.chatgpt</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.chromecast</artifactId>

View File

@ -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

View File

@ -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 <https://platform.openai.com/account/api-keys>.
| 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="<your api key here>"] {
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.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>4.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.binding.chatgpt</artifactId>
<name>openHAB Add-ons :: Bundles :: ChatGPT Binding</name>
</project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.chatgpt-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-binding-chatgpt" description="ChatGPT Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.chatgpt/${project.version}</bundle>
</feature>
</features>

View File

@ -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";
}

View File

@ -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;
}

View File

@ -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 = "";
}

View File

@ -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<String> 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<String> 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<String> getModels() {
return models;
}
@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return List.of(ChatGPTModelOptionProvider.class);
}
}

View File

@ -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<ThingTypeUID> 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;
}
}

View File

@ -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<ParameterOption> getParameterOptions(URI uri, String param, @Nullable String context,
@Nullable Locale locale) {
if ("model".equals(param)) {
List<ParameterOption> 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() {
}
}

View File

@ -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<Choice> choices;
private String id;
private String object;
private int created;
private String model;
public List<Choice> 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;
}
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon:addon id="chatgpt" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
<type>binding</type>
<name>ChatGPT Binding</name>
<description>This binding allows interaction with OpenAI's ChatGPT.</description>
<connection>cloud</connection>
</addon:addon>

View File

@ -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

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="chatgpt"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="account" extensible="chat">
<label>OpenAI Account</label>
<description>Account at OpenAI that is used for accessing the ChatGPT API.</description>
<channels>
<channel id="chat" typeId="chat"/>
</channels>
<config-description>
<parameter name="apiKey" type="text" required="true">
<context>password</context>
<label>API Key</label>
<description>API key to access the account</description>
</parameter>
</config-description>
</thing-type>
<channel-type id="chat">
<item-type>String</item-type>
<label>Chat</label>
<description>A chat session</description>
<autoUpdatePolicy>veto</autoUpdatePolicy>
<config-description>
<parameter name="model" type="text">
<label>Model</label>
<description>The model to be used for the responses</description>
<limitToOptions>false</limitToOptions>
<default>gpt-3.5-turbo</default>
</parameter>
<parameter name="temperature" type="decimal" min="0" max="2">
<label>Temperature</label>
<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.</description>
<default>0.5</default>
</parameter>
<parameter name="systemMessage" type="text">
<label>System Message</label>
<description>The system message helps set the behavior of the assistant.</description>
</parameter>
<parameter name="maxTokens" type="decimal">
<label>Maximum Number of Tokens</label>
<description>The maximum number of tokens to generate in the completion.</description>
<default>500</default>
<advanced>true</advanced>
</parameter>
</config-description>
</channel-type>
</thing:thing-descriptions>

View File

@ -90,6 +90,7 @@
<module>org.openhab.binding.buienradar</module>
<module>org.openhab.binding.caddx</module>
<module>org.openhab.binding.cbus</module>
<module>org.openhab.binding.chatgpt</module>
<module>org.openhab.binding.chromecast</module>
<module>org.openhab.binding.cm11a</module>
<module>org.openhab.binding.comfoair</module>