mirror of
https://github.com/matrixgpt/matrix-chatgpt-bot.git
synced 2024-10-01 05:25:41 +00:00
Merge pull request #66 from matrixgpt/configurable-context
Add support for configurable context levels.
This commit is contained in:
commit
99935aed6f
@ -41,6 +41,9 @@ OPENAI_LOGIN_TYPE=google
|
|||||||
# Set the next line to true if you are using a ChatGPT pro account.
|
# Set the next line to true if you are using a ChatGPT pro account.
|
||||||
OPENAI_PRO=false
|
OPENAI_PRO=false
|
||||||
|
|
||||||
|
# Set the ChatGPT conversation context to 'thread', 'room' or 'both'.
|
||||||
|
CHATGPT_CONTEXT=thread
|
||||||
|
|
||||||
# Matrix Static Settings (required, see notes)
|
# Matrix Static Settings (required, see notes)
|
||||||
# Defaults to "https://matrix.org"
|
# Defaults to "https://matrix.org"
|
||||||
MATRIX_HOMESERVER_URL=
|
MATRIX_HOMESERVER_URL=
|
||||||
|
@ -26,6 +26,7 @@ export const {
|
|||||||
OPENAI_PASSWORD,
|
OPENAI_PASSWORD,
|
||||||
OPENAI_LOGIN_TYPE,
|
OPENAI_LOGIN_TYPE,
|
||||||
OPENAI_PRO,
|
OPENAI_PRO,
|
||||||
|
CHATGPT_CONTEXT,
|
||||||
CHATGPT_TIMEOUT
|
CHATGPT_TIMEOUT
|
||||||
} = parseEnv(process.env, {
|
} = parseEnv(process.env, {
|
||||||
DATA_PATH: { schema: z.string().default("./storage"), description: "Set to /storage/ if using docker, ./storage if running without" },
|
DATA_PATH: { schema: z.string().default("./storage"), description: "Set to /storage/ if using docker, ./storage if running without" },
|
||||||
@ -50,5 +51,6 @@ export const {
|
|||||||
OPENAI_PASSWORD: { schema: z.string().min(1), description: "Set password of OpenAI's account" },
|
OPENAI_PASSWORD: { schema: z.string().min(1), description: "Set password of OpenAI's account" },
|
||||||
OPENAI_LOGIN_TYPE: { schema: z.enum(["google", "openai", "microsoft"]).default("google"), description: "Set authentication provider to 'google', 'openai' or 'microsoft'" },
|
OPENAI_LOGIN_TYPE: { schema: z.enum(["google", "openai", "microsoft"]).default("google"), description: "Set authentication provider to 'google', 'openai' or 'microsoft'" },
|
||||||
OPENAI_PRO: { schema: z.boolean().default(false), description: "Set to true if you have a paid ChatGPT subscription." },
|
OPENAI_PRO: { schema: z.boolean().default(false), description: "Set to true if you have a paid ChatGPT subscription." },
|
||||||
CHATGPT_TIMEOUT: { schema: z.number().default(2 * 60 * 1000), description: "Set number of milliseconds to wait for CHATGPT responses" }
|
CHATGPT_TIMEOUT: { schema: z.number().default(2 * 60 * 1000), description: "Set number of milliseconds to wait for ChatGPT responses" },
|
||||||
|
CHATGPT_CONTEXT: { schema: z.enum(["thread", "room", "both"]).default("thread"), description: "Set the ChatGPT conversation context to 'thread', 'room' or 'both'" }
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ChatGPTAPIBrowser } from "chatgpt";
|
import { ChatGPTAPIBrowser } from "chatgpt";
|
||||||
import { LogService, MatrixClient, UserID } from "matrix-bot-sdk";
|
import { LogService, MatrixClient, UserID } from "matrix-bot-sdk";
|
||||||
import { CHATGPT_TIMEOUT, MATRIX_DEFAULT_PREFIX_REPLY, MATRIX_DEFAULT_PREFIX, MATRIX_BLACKLIST, MATRIX_WHITELIST, MATRIX_RICH_TEXT, MATRIX_PREFIX_DM } from "./env.js";
|
import { CHATGPT_CONTEXT, CHATGPT_TIMEOUT, MATRIX_DEFAULT_PREFIX_REPLY, MATRIX_DEFAULT_PREFIX, MATRIX_BLACKLIST, MATRIX_WHITELIST, MATRIX_RICH_TEXT, MATRIX_PREFIX_DM } from "./env.js";
|
||||||
import { RelatesTo, MessageEvent, StoredConversation, StoredConversationConfig } from "./interfaces.js";
|
import { RelatesTo, MessageEvent, StoredConversation, StoredConversationConfig } from "./interfaces.js";
|
||||||
import { sendChatGPTMessage, sendError, sendThreadReply } from "./utils.js";
|
import { sendChatGPTMessage, sendError, sendThreadReply } from "./utils.js";
|
||||||
|
|
||||||
@ -44,8 +44,20 @@ export default class CommandHandler {
|
|||||||
return (!isReplyOrThread && relatesTo.event_id !== undefined) ? relatesTo.event_id : event.event_id;
|
return (!isReplyOrThread && relatesTo.event_id !== undefined) ? relatesTo.event_id : event.event_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getStoredConversation(rootEventId: string): Promise<StoredConversation> {
|
private getStorageKey(event: MessageEvent, roomId: string): string {
|
||||||
const storedValue: string = await this.client.storageProvider.readValue('gpt-' + rootEventId)
|
const rootEventId: string = this.getRootEventId(event)
|
||||||
|
if (CHATGPT_CONTEXT == "room") {
|
||||||
|
return roomId
|
||||||
|
} else if (CHATGPT_CONTEXT == "thread") {
|
||||||
|
return rootEventId
|
||||||
|
} else { // CHATGPT_CONTEXT set to both.
|
||||||
|
return (rootEventId !== event.event_id) ? rootEventId : roomId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getStoredConversation(storageKey: string, roomId: string): Promise<StoredConversation> {
|
||||||
|
let storedValue: string = await this.client.storageProvider.readValue('gpt-' + storageKey)
|
||||||
|
if (storedValue == undefined && storageKey != roomId) storedValue = await this.client.storageProvider.readValue('gpt-' + roomId)
|
||||||
return (storedValue !== undefined) ? JSON.parse(storedValue) : undefined;
|
return (storedValue !== undefined) ? JSON.parse(storedValue) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,8 +103,8 @@ export default class CommandHandler {
|
|||||||
try {
|
try {
|
||||||
if (this.shouldIgnore(event)) return;
|
if (this.shouldIgnore(event)) return;
|
||||||
|
|
||||||
const rootEventId = this.getRootEventId(event);
|
const storageKey = this.getStorageKey(event, roomId);
|
||||||
const storedConversation = await this.getStoredConversation(rootEventId);
|
const storedConversation = await this.getStoredConversation(storageKey, roomId);
|
||||||
const config = this.getConfig(storedConversation);
|
const config = this.getConfig(storedConversation);
|
||||||
|
|
||||||
const shouldBePrefixed = await this.shouldBePrefixed(config, roomId, event)
|
const shouldBePrefixed = await this.shouldBePrefixed(config, roomId, event)
|
||||||
@ -112,13 +124,13 @@ export default class CommandHandler {
|
|||||||
const result = await sendChatGPTMessage(this.chatGPT, await bodyWithoutPrefix, storedConversation);
|
const result = await sendChatGPTMessage(this.chatGPT, await bodyWithoutPrefix, storedConversation);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.client.setTyping(roomId, false, 500),
|
this.client.setTyping(roomId, false, 500),
|
||||||
sendThreadReply(this.client, roomId, rootEventId, `${result.response}`, MATRIX_RICH_TEXT)
|
sendThreadReply(this.client, roomId, this.getRootEventId(event), `${result.response}`, MATRIX_RICH_TEXT)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await this.client.storageProvider.storeValue('gpt-' + rootEventId, JSON.stringify({
|
const storedConfig = ((storedConversation !== undefined && storedConversation.config !== undefined) ? storedConversation.config : {})
|
||||||
conversationId: result.conversationId, messageId: result.messageId,
|
const configString: string = JSON.stringify({conversationId: result.conversationId, messageId: result.messageId, config: storedConfig})
|
||||||
config: ((storedConversation !== undefined && storedConversation.config !== undefined) ? storedConversation.config : {}),
|
await this.client.storageProvider.storeValue('gpt-' + storageKey, configString);
|
||||||
}));
|
if ((storageKey === roomId) && (CHATGPT_CONTEXT === "both")) await this.client.storageProvider.storeValue('gpt-' + event.event_id, configString);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user