Skip to content

Commit

Permalink
Beta3 Candidate - New features: YT Summarisation, PDF summarisation \…
Browse files Browse the repository at this point in the history
…w GCS store for Dialogflow CX Chatbot grounding(TBC). Google Search \w Summarisation and other improvements
  • Loading branch information
jpantsjoha committed Nov 19, 2024
1 parent 5f63a3f commit 0118aba
Show file tree
Hide file tree
Showing 36 changed files with 7,686 additions and 3,475 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.env
17 changes: 0 additions & 17 deletions Dockerfile

This file was deleted.

340 changes: 191 additions & 149 deletions README.md

Large diffs are not rendered by default.

173 changes: 173 additions & 0 deletions chat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// chat.js

const { VertexAI } = require('@google-cloud/vertexai');
const { ChatModel } = require('@google-cloud/vertexai').largeLanguageModels;
const {
VERTEX_AI_LOCATION,
SUMMARIZATION_TEMPERATURE,
SUMMARIZATION_MAX_OUTPUT_TOKENS,
SUMMARIZATION_TOP_P,
SUMMARIZATION_TOP_K,
} = require('./config');

// Global debug flag
const DEBUG = true; // Set to false to disable debug messages

// Function to log debug messages
function debugLog(message, ...args) {
if (DEBUG) {
console.log('[DEBUG chat.js]', message, ...args);
}
}

module.exports = function (app) {
// Function to generate chat response using Vertex AI
async function generateChatResponse(prompt) {
debugLog('Initializing Vertex AI for chat response');

// Set up Vertex AI client with service account authentication
const vertexAI = new VertexAI({
projectId: process.env.GOOGLE_CLOUD_PROJECT,
location: VERTEX_AI_LOCATION,
});

// Configure the ChatModel
const model = new ChatModel({
vertexAI,
model: 'chat-bison@latest',
// Optionally, you can specify parameters here
// temperature: SUMMARIZATION_TEMPERATURE,
// maxOutputTokens: SUMMARIZATION_MAX_OUTPUT_TOKENS,
// topP: SUMMARIZATION_TOP_P,
// topK: SUMMARIZATION_TOP_K,
});

// Start the chat session
const chatSession = model.startChat({
context: 'You are BriefOps, a Slack assistant.',
examples: [],
});

try {
debugLog('Sending prompt to Vertex AI:', prompt);
const response = await chatSession.sendMessage(prompt);

const responseText = response.text;
debugLog('Received response from Vertex AI:', responseText);

return responseText;
} catch (error) {
console.error('Error during chat response generation:', error);
throw new Error('An error occurred while generating the response.');
}
}

// Function to fetch and concatenate all messages from the thread
async function fetchThreadContext(app, channelId, threadTs) {
try {
debugLog(
'Fetching thread context for channel:',
channelId,
'thread_ts:',
threadTs
);
let messages = [];
let hasMore = true;
let cursor;

while (hasMore) {
const result = await app.client.conversations.replies({
token: process.env.SLACK_BOT_TOKEN,
channel: channelId,
ts: threadTs,
cursor: cursor,
limit: 200, // Max limit per API call
});

messages = messages.concat(result.messages || []);
hasMore = result.has_more;
cursor = result.response_metadata?.next_cursor;
}

// Concatenate all messages in the thread to provide context
const context = messages.map((msg) => msg.text).join('\n');
debugLog('Aggregated thread context:', context);
return context;
} catch (error) {
console.error('Error fetching thread context:', error);
throw new Error('Failed to fetch the thread context.');
}
}

// Function to get the bot user ID dynamically
async function getBotUserId(app) {
try {
const authResult = await app.client.auth.test();
const botUserId = authResult.user_id;
debugLog('Retrieved bot user ID:', botUserId);
return botUserId;
} catch (error) {
console.error('Error retrieving bot user ID:', error);
throw new Error('Failed to retrieve bot user ID.');
}
}

// Handle @briefops mentions for direct chat interaction
app.event('app_mention', async ({ event, say }) => {
try {
debugLog('app_mention event received:', event);

// Get the bot user ID
let botUserId = process.env.SLACK_BOT_USER_ID;
if (!botUserId) {
debugLog('SLACK_BOT_USER_ID not set, retrieving dynamically.');
botUserId = await getBotUserId(app);
process.env.SLACK_BOT_USER_ID = botUserId; // Set it for future use
} else {
debugLog('Using SLACK_BOT_USER_ID from environment:', botUserId);
}

// Remove only the bot's mention from the text
const mentionRegex = new RegExp(`<@${botUserId}>`, 'g');
const userMessage = event.text.replace(mentionRegex, '').trim();
debugLog('User message after removing bot mention:', userMessage);

if (!userMessage) {
debugLog('User message is empty after removing bot mention');
await say({
text: `:information_source: Please provide some text to process.`,
thread_ts: event.ts,
});
return;
}

// Fetch the complete thread context
const threadContext = await fetchThreadContext(
app,
event.channel,
event.thread_ts || event.ts
);

// Prepare input for the model, including thread context
const prompt = `Consider the entire thread context for accuracy and relevance.\n\nContext:\n${threadContext}\n\nUser query:\n${userMessage}`;
debugLog('Prepared prompt for model:', prompt);

// Generate chat response
const response = await generateChatResponse(prompt);
debugLog('Generated response:', response);

// Send the response back to Slack
await say({
text: `*Response:*\n${response}`,
thread_ts: event.ts,
});
} catch (error) {
console.error('Error handling @briefops chat interaction:', error);
await say({
text:
error.message || 'An error occurred while processing your request.',
thread_ts: event.ts,
});
}
});
};
30 changes: 24 additions & 6 deletions config.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
// config.js

require('dotenv').config();

module.exports = {

//yt
GOOGLE_API_KEY: process.env.GOOGLE_API_KEY,
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET,
OAUTH2_REDIRECT_URI: process.env.OAUTH2_REDIRECT_URI || 'http://localhost:8080/oauth2callback',
//GOOGLE SEARCH
SEARCH_ENGINE_ID: process.env.SEARCH_ENGINE_ID || 'your-search-engine-id',

// Free tier limits
FREE_TIER_DAILY_LIMIT: process.env.FREE_TIER_DAILY_LIMIT
? parseInt(process.env.FREE_TIER_DAILY_LIMIT)
: 100, // Default to 10 summaries per day
: 100, // Default to 100 summaries per day

FREE_TIER_MAX_DAYS: process.env.FREE_TIER_MAX_DAYS
? parseInt(process.env.FREE_TIER_MAX_DAYS)
: 14, // Default to 7 days
: 14, // Default to 14 days

// Vertex AI configuration
VERTEX_AI_MODEL_PDF: process.env.VERTEX_AI_MODEL_PDF || 'gemini-1.5-flash-002',
VERTEX_AI_MODEL_TEXT: process.env.VERTEX_AI_MODEL_TEXT || 'gemini-1.5-flash-002',
VERTEX_AI_MODEL: process.env.VERTEX_AI_MODEL || 'gemini-1.5-flash-002',
VERTEX_AI_LOCATION: process.env.VERTEX_AI_LOCATION || 'us-central1', // Default location

Expand All @@ -23,7 +32,7 @@ module.exports = {

SUMMARIZATION_MAX_OUTPUT_TOKENS: process.env.SUMMARIZATION_MAX_OUTPUT_TOKENS
? parseInt(process.env.SUMMARIZATION_MAX_OUTPUT_TOKENS)
: 1000, // Default max output tokens
: 1024, // Adjusted for typical usage

SUMMARIZATION_TOP_P: process.env.SUMMARIZATION_TOP_P
? parseFloat(process.env.SUMMARIZATION_TOP_P)
Expand All @@ -34,5 +43,14 @@ module.exports = {
: 40, // Default top_k

// Slack app configuration
LOG_LEVEL: process.env.LOG_LEVEL || 'debug', // Set default log level to 'info' for less verbosity
LOG_LEVEL: process.env.LOG_LEVEL || 'debug', // Set default log level to 'debug' for verbosity

// Google Cloud configuration
GOOGLE_CLOUD_PROJECT: process.env.GOOGLE_CLOUD_PROJECT || 'your-google-cloud-project-id',

//DIALOGFLOW CX
DIALOGFLOW_AGENT_ID: process.env.DIALOGFLOW_AGENT_ID || 'your-dialogflow-agent-id',
GCS_BUCKET_NAME: process.env.GCS_BUCKET_NAME || 'dialogflowcx-bucket-briefops'


};
32 changes: 32 additions & 0 deletions dialogflowClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// dialogflowClient.js

const { SessionsClient } = require('@google-cloud/dialogflow-cx');
const { GOOGLE_CLOUD_PROJECT, DIALOGFLOW_AGENT_ID } = require('./config');

const client = new SessionsClient();

async function detectIntentText(sessionId, text, languageCode = 'en') {
const sessionPath = client.projectLocationAgentSessionPath(
GOOGLE_CLOUD_PROJECT,
'global', // Replace with your region if not 'global'
DIALOGFLOW_AGENT_ID,
sessionId
);

const request = {
session: sessionPath,
queryInput: {
text: {
text: text,
},
languageCode: languageCode,
},
};

const [response] = await client.detectIntent(request);
return response;
}

module.exports = {
detectIntentText,
};
Loading

0 comments on commit 0118aba

Please sign in to comment.