Skip to content
This repository has been archived by the owner on Dec 20, 2022. It is now read-only.

Commit

Permalink
support conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
huan9huan committed Dec 7, 2022
1 parent e383f36 commit 1bbc799
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 35 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ make Scopes as:
![setup command](./img/command.png)
where
- `/chatgpt` command: direct send question to ChatGPT
- `/reset-chatgpt-conversation` command: reset the conversation thread to cleanup the context
- optional: `/set-chatgpt-token` command can set new Bearer Auth token which are copied from ChatGPT website
- optional: `/print-chatgpt-token` command can print current Bearer Auth token

Expand Down
50 changes: 29 additions & 21 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,29 @@ export async function fetchSSE(resource, options) {
}


export async function getAnswer(question, accessToken): Promise<string> {
let total = '';
export async function getAnswer(question: string, accessToken: string, conversationId?: string, parentId?: string): Promise<{answer: string, conversationId: string; id: string;}> {
let total = ''; // answer content
let id = ''; // message id
parentId = parentId || uuidv4();
const query: any = {
action: "next",
messages: [
{
id: uuidv4(),
role: "user",
content: {
content_type: "text",
parts: [question],
},
},
],
model: "text-davinci-002-render",
parent_message_id: parentId,
};
if(conversationId) {
console.log('use conv id ' + conversationId);
query.conversation_id = conversationId;
}
return new Promise((r,j) => {
fetchSSE("https://chat.openai.com/backend-api/conversation", {
method: "POST",
Expand All @@ -40,35 +61,22 @@ export async function getAnswer(question, accessToken): Promise<string> {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
action: "next",
// conversation_id: "5aceeec4-0870-4553-97c7-9512b447493c",
messages: [
{
id: uuidv4(),
role: "user",
content: {
content_type: "text",
parts: [question],
},
},
],
model: "text-davinci-002-render",
parent_message_id: uuidv4(),
}),
onMessage(message) {
body: JSON.stringify(query),
onMessage: (message) => {
console.debug("sse message", message);
if (message === "[DONE]") {
r(total);
console.log("message answered done", total);
r({answer: total, conversationId, id});
} else {
const data = JSON.parse(message);
const text = data.message?.content?.parts?.[0];
if (text) {
total = text;
}
conversationId = data.conversation_id || conversationId;
id = data.message?.id;
}
},
});
})

}
40 changes: 26 additions & 14 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

import { App } from "@slack/bolt";
import { getAnswer } from "./api";
import { v4 as uuidv4 } from "uuid";
require('dotenv').config();

const app = new App({
Expand All @@ -10,54 +11,65 @@ const app = new App({
appToken: process.env.SLACKBOT_APP_TOKEN, // Token from the App-level Token that we created
});

const STATES = {
instanceId: uuidv4(),
token: process.env.CHATGPT_AUTH_TOKEN,
conversationId: undefined, // first time will be generated by server, then save it until reset
parentId: undefined, // parent message id
};

(async () => {
await app.start();
console.log('⚡️ ChatGPT Bot App started');
console.log(`⚡️ ChatGPT-${STATES.instanceId} Bot App started`);
})();

const CACHES = {
token: process.env.CHATGPT_AUTH_TOKEN
}

const handle = async (question: string, say: Function) => {
try {
const result = await getAnswer(question, CACHES.token)
console.debug(`${STATES.instanceId} recv question '${question}'`);
const {answer: result, conversationId, id} = await getAnswer(question, STATES.token, STATES.conversationId, STATES.parentId);
STATES.conversationId = conversationId;
STATES.parentId = id;
console.log(`chatgpt-${STATES.instanceId}/${conversationId} Q: '${question}', A: ${result}`);
say(result);
} catch (error) {
console.error(error);
say(`Bot error: \`${error.message}\``);
say(`hatgpt-${STATES.instanceId} error: \`${error.message}\``);
}
}
app.message(/.*/, async ({context, say, payload }) => {
return handle(context['matches'][0], say);
});
app.event("app_mention", async ({context, event, say}) => {
const q = event.text.replace(`<@${context.botUserId}>`, '');
console.log('recv question by mention: ', q);
return handle(q, say);
});
app.command("/chatgpt", async ({ command, ack, say }) => {
await ack();
return handle(command.text, say);
});

app.command("/reset-chatgpt-conversation", async ({ command, ack, say }) => {
await ack();
STATES.conversationId = undefined;
STATES.parentId = undefined;
say(`\`chatgpt-${STATES.instanceId}\` conversation reset done.`);
});
app.command("/print-chatgpt-token", async ({ command, ack, say }) => {
try {
await ack();
say(`chatgpt auth token using : \`${CACHES.token || "<not setup>"}\``);
say(`\`chatgpt-${STATES.instanceId}\` auth token using : \`${STATES.token || "<not setup>"}\``);
} catch (error) {
console.error(error);
say(`tchatgpt auth token get error: ${error.message}`);
say(`\`chatgpt-${STATES.instanceId}\` auth token get error: ${error.message}`);
}
});
app.command("/set-chatgpt-token", async ({ command, ack, say }) => {
try {
await ack();
let txt:any = command.text; // The inputted parameters
CACHES.token = txt;
say(`chatgpt auth setup done, current value as :\`${txt}\``);
STATES.token = txt;
say(`\`chatgpt-${STATES.instanceId}\` auth setup done, current value as :\`${txt}\``);
} catch (error) {
console.error(error);
say(`chatgpt auth setup fail, error: + \`${error.message}\``);
say(`\`chatgpt-${STATES.instanceId}\` auth setup fail, error: + \`${error.message}\``);
}
});

0 comments on commit 1bbc799

Please sign in to comment.