Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Option to Disable Titling, Config Titling Model, and Title Prompt Improvements #977

Merged
merged 2 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ OPENAI_API_KEY=user_provided
# Leave it blank to use internal settings.
# OPENAI_MODELS=gpt-3.5-turbo,gpt-3.5-turbo-16k,gpt-3.5-turbo-0301,text-davinci-003,gpt-4,gpt-4-0314,gpt-4-0613

# Titling is enabled by default when initiating a conversation.
# Uncomment the following variable to disable this feature.
# TITLE_CONVO=false

# The model used for titling by default is gpt-3.5-turbo-0613 to assure it works with the default method.
# gpt-3.5-turbo should also work when using the official API (and not a reverse proxy).
# You can change the model used by uncommenting the following and setting it to the model you want
# Must be compatible with the OpenAI Endpoint.
# OPENAI_TITLE_MODEL=gpt-3.5-turbo

# Reverse proxy settings for OpenAI:
# https://github.com/waylaidwanderer/node-chatgpt-api#using-a-reverse-proxy
# OPENAI_REVERSE_PROXY=
Expand Down
11 changes: 7 additions & 4 deletions api/app/clients/OpenAIClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const BaseClient = require('./BaseClient');
const ChatGPTClient = require('./ChatGPTClient');
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken');
const { maxTokensMap, genAzureChatCompletion } = require('../../utils');
const { truncateText } = require('./prompts');
const { runTitleChain } = require('./chains');
const { createLLM } = require('./llm');

Expand Down Expand Up @@ -406,12 +407,14 @@ class OpenAIClient extends BaseClient {
async titleConvo({ text, responseText = '' }) {
let title = 'New Chat';
const convo = `||>User:
"${text}"
"${truncateText(text)}"
||>Response:
"${JSON.stringify(responseText)}"`;
"${JSON.stringify(truncateText(responseText))}"`;

const { OPENAI_TITLE_MODEL } = process.env ?? {};

const modelOptions = {
model: 'gpt-3.5-turbo-0613',
model: OPENAI_TITLE_MODEL ?? 'gpt-3.5-turbo-0613',
temperature: 0.2,
presence_penalty: 0,
frequency_penalty: 0,
Expand Down Expand Up @@ -446,7 +449,7 @@ class OpenAIClient extends BaseClient {
} catch (e) {
console.error(e.message);
console.log('There was an issue generating title with LangChain, trying the old method...');
modelOptions.model = 'gpt-3.5-turbo';
modelOptions.model = OPENAI_TITLE_MODEL ?? 'gpt-3.5-turbo';
const instructionsPayload = [
{
role: 'system',
Expand Down
2 changes: 1 addition & 1 deletion api/app/clients/chains/runTitleChain.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const createLanguageChain = ({ llm }) =>
});

const titleSchema = z.object({
title: z.string().describe('The title-cased title of the conversation in the given language.'),
title: z.string().describe('The conversation title in title-case, in the given language.'),
});
const createTitleChain = ({ llm, convo }) => {
const titlePrompt = createTitlePrompt({ convo });
Expand Down
2 changes: 2 additions & 0 deletions api/app/clients/prompts/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const instructions = require('./instructions');
const titlePrompts = require('./titlePrompts');
const refinePrompts = require('./refinePrompts');
const truncateText = require('./truncateText');

module.exports = {
...refinePrompts,
...instructions,
...titlePrompts,
truncateText,
};
2 changes: 1 addition & 1 deletion api/app/clients/prompts/titlePrompts.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const createTitlePrompt = ({ convo }) => {
const titlePrompt = new ChatPromptTemplate({
promptMessages: [
SystemMessagePromptTemplate.fromTemplate(
`Write a concise title for this conversation in the given language. Title in 5 Words or Less. No Punctuation or Quotation. All first letters of every word must be capitalized (resembling title-case), written in the given Language.
`Write a concise title for this conversation in the given language. Title in 5 Words or Less. No Punctuation or Quotation. Must be in Title Case, written in the given Language.
${convo}`,
),
HumanMessagePromptTemplate.fromTemplate('Language: {language}'),
Expand Down
10 changes: 10 additions & 0 deletions api/app/clients/prompts/truncateText.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const MAX_CHAR = 255;

function truncateText(text) {
if (text.length > MAX_CHAR) {
return `${text.slice(0, MAX_CHAR)}... [text truncated for brevity]`;
}
return text;
}

module.exports = truncateText;
6 changes: 6 additions & 0 deletions api/app/titleConvoBing.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
const { isEnabled } = require('../server/utils');
const throttle = require('lodash/throttle');

const titleConvo = async ({ text, response }) => {
let title = 'New Chat';
const { TITLE_CONVO = 'true' } = process.env ?? {};
if (!isEnabled(TITLE_CONVO)) {
return title;
}

const { BingAIClient } = await import('@waylaidwanderer/chatgpt-api');
const titleGenerator = new BingAIClient({
userToken: process.env.BINGAI_TOKEN,
Expand Down
6 changes: 6 additions & 0 deletions api/server/routes/endpoints/openAI/addTitle.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
const { isEnabled } = require('../../../utils');
const { saveConvo } = require('../../../../models');

const addTitle = async (req, { text, response, client }) => {
const { TITLE_CONVO = 'true' } = process.env ?? {};
if (!isEnabled(TITLE_CONVO)) {
return;
}

const title = await client.titleConvo({ text, responseText: response?.text });
await saveConvo(req.user.id, {
conversationId: response.conversationId,
Expand Down
Loading