Skip to content
Snippets Groups Projects

fixed the gemini API issues

Open Miran Siddique requested to merge issue/gptbot-3519765:miran-sddq-api-branch into main
4 files
+ 109
86
Compare changes
  • Side-by-side
  • Inline
Files
4
+ 101
78
@@ -8,11 +8,28 @@
const chatbox = document.querySelector(".chatbox");
const chatInput = document.querySelector(".chat-input textarea");
const sendChatBtn = document.querySelector("#send-btn");
const micBtn = document.querySelector("#mic-btn");
//const micBtn = document.querySelector("#mic-btn");
const resizeHandle = document.querySelector(".resize-handle");
if (!chatbot || !chatbotToggler || !closeBtn || !chatbox ||
!chatInput || !sendChatBtn || !micBtn || !resizeHandle) {
// Check if all required elements exist
const elementsToCheck = {
"chatbot": chatbot,
"chatbotToggler": chatbotToggler,
"closeBtn": closeBtn,
"chatbox": chatbox,
"chatInput": chatInput,
"sendChatBtn": sendChatBtn,
//"micBtn": micBtn,
"resizeHandle": resizeHandle
};
for (const [name, element] of Object.entries(elementsToCheck)) {
if (!element) {
console.error(`Missing element: ${name}`);
}
}
if (!chatbot || !chatbotToggler || !closeBtn || !chatbox || !chatInput || !sendChatBtn || /* !micBtn || */ !resizeHandle) {
console.error("One or more chatbot elements not found");
return;
}
@@ -35,9 +52,9 @@
}
}
if (!settings.enable_speech_to_text) {
/* if (!settings.enable_speech_to_text) {
micBtn.style.display = 'none';
}
} */
// Update initial timestamp for the welcome message
updateInitialTimestamp();
@@ -49,7 +66,7 @@
let GROQ_MODEL = 'llama3-70b-8192';
let GEMINI_MODEL = 'gemini-2.0-flash';
// First try to get settings from drupalSettings
// First try to get settings from drupalSettings
if (drupalSettings && drupalSettings.chatbot) {
console.log('Loading settings from drupalSettings:', drupalSettings.chatbot);
API_KEY = drupalSettings.chatbot.api_key;
@@ -64,24 +81,24 @@
if (!API_KEY || !API_URL) {
console.log('Settings not found in drupalSettings, fetching from API...');
fetch('/api/chatbot/settings')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json();
})
.then(data => {
API_KEY = data.api_key;
API_URL = data.endpoint;
API_PROVIDER = data.api_provider || 'openai';
OPENAI_MODEL = data.openai_model || 'gpt-4';
GROQ_MODEL = data.groq_model || 'llama3-70b-8192';
GEMINI_MODEL = data.gemini_model || 'gemini-2.0-flash';
console.log('Chatbot settings loaded successfully. Using provider:', API_PROVIDER);
})
.catch(error => {
console.error('Error fetching chatbot settings:', error);
});
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json();
})
.then(data => {
API_KEY = data.api_key;
API_URL = data.endpoint;
API_PROVIDER = data.api_provider || 'openai';
OPENAI_MODEL = data.openai_model || 'gpt-4';
GROQ_MODEL = data.groq_model || 'llama3-70b-8192';
GEMINI_MODEL = data.gemini_model || 'gemini-2.0-flash';
console.log('Chatbot settings loaded successfully. Using provider:', API_PROVIDER);
})
.catch(error => {
console.error('Error fetching chatbot settings:', error);
});
}
let userMessage = null;
@@ -134,27 +151,6 @@
return chatLi;
};
// Create a typing indicator
const createTypingIndicator = () => {
const chatLi = document.createElement("li");
chatLi.classList.add("chat", "incoming");
const currentTime = getCurrentTime();
chatLi.innerHTML = `
<div class="bot-icon-container">
<span class="material-symbols-outlined">smart_toy</span>
<div class="bot-label">GPTBot</div>
<div class="bot-timestamp">${currentTime}</div>
</div>
<div class="typing-indicator">
<span></span>
<span></span>
<span></span>
</div>
`;
return chatLi;
};
// Function to prepare request body based on the selected API provider
const prepareRequestBody = (message) => {
switch (API_PROVIDER) {
@@ -170,8 +166,15 @@
};
case 'gemini':
return {
contents: [{role: "user", parts: [{text: message}]}],
model: GEMINI_MODEL,
contents: [
{
role: "user",
parts: [
{text: message}
]
}
]
// Not adding model here, it goes in the URL for Gemini
};
default:
return {
@@ -181,15 +184,21 @@
}
};
// Function to extract response from API based on provider
const extractResponse = (data) => {
console.log("Raw response data:", data);
switch (API_PROVIDER) {
case 'openai':
return data.choices[0].message.content.trim();
case 'groq':
return data.choices[0].message.content.trim();
case 'gemini':
return data.candidates[0].content.parts[0].text.trim();
if (data.candidates && data.candidates[0] && data.candidates[0].content) {
return data.candidates[0].content.parts[0].text.trim();
} else {
console.error("Unexpected Gemini response structure:", data);
throw new Error("Invalid Gemini response format");
}
default:
return data.choices[0].message.content.trim();
}
@@ -206,42 +215,64 @@
typingIndicator.classList.add("typing-indicator");
typingIndicator.innerHTML = "<span></span><span></span><span></span>";
messageElement.appendChild(typingIndicator);
// Check if API settings are loaded
if (!API_KEY || !API_URL) {
console.error("API settings not loaded. API_KEY:", !!API_KEY, "API_URL:", !!API_URL);
messageElement.innerHTML = ""; // Clear typing indicator
messageElement.textContent = "Chatbot is not configured properly. Please try again later.";
messageElement.classList.add("error");
return;
}
let url;
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
"Content-Type": "application/json"
},
body: JSON.stringify(prepareRequestBody(userMessage))
};
fetch(API_URL, requestOptions)
// Handle different API providers
if (API_PROVIDER === 'gemini') {
// For Gemini, we need to use the correct Google API URL format
const baseUrl = 'https://generativelanguage.googleapis.com/v1beta/models/' +
encodeURIComponent(GEMINI_MODEL) + ':generateContent';
url = `${baseUrl}?key=${encodeURIComponent(API_KEY)}`;
console.log(`Making Gemini API request to ${url.replace(API_KEY, '[REDACTED]')}`);
} else {
// For OpenAI and Groq, we use Bearer token authentication with the provided endpoint
url = API_URL;
requestOptions.headers["Authorization"] = `Bearer ${API_KEY}`;
console.log(`Making ${API_PROVIDER} API request to ${url}`);
}
// Log request body for debugging
console.log("Request body:", JSON.parse(requestOptions.body));
fetch(url, requestOptions)
.then(res => {
console.log("API response status:", res.status, res.statusText);
if (!res.ok) {
throw new Error(`API responded with status ${res.status}: ${res.statusText}`);
return res.text().then(text => {
console.error("API error response:", text);
throw new Error(`API responded with status ${res.status}: ${res.statusText}`);
});
}
return res.json();
})
.then(data => {
try{
// Remove typing indicator
messageElement.innerHTML = "";
messageElement.textContent = extractResponse(data);
} catch (error) {
console.error("Error extracting response:", error,data);
messageElement.classList.add("error");
messageElement.textContent = "Error processing response from AI provider.";
}
try {
messageElement.textContent = extractResponse(data);
} catch (error) {
console.error('Error extracting response:', error, data);
messageElement.classList.add("error");
messageElement.textContent = "Error processing response from AI provider.";
}
})
.catch((error) => {
console.error('API request failed:', error);
@@ -266,16 +297,8 @@
// Slight delay before showing the bot's response to allow outgoing animation to finish
setTimeout(() => {
// Create incoming chat element with empty text first
const incomingChatLi = createChatLi("Thinking...", "incoming");
chatbox.appendChild(incomingChatLi);
// Add the typing indicator inside the paragraph
const typingIndicator = document.createElement("div");
typingIndicator.classList.add("typing-indicator");
typingIndicator.innerHTML = "<span></span><span></span><span></span>";
incomingChatLi.querySelector("p").appendChild(typingIndicator);
chatbox.scrollTo(0, chatbox.scrollHeight);
// Generate response with a slight delay
@@ -290,9 +313,9 @@
if (SpeechRecognition) {
const recognition = new SpeechRecognition();
recognition.onstart = () => {
/* recognition.onstart = () => {
micBtn.classList.add('listening');
};
}; */
recognition.onresult = (event) => {
const current = event.resultIndex;
@@ -301,15 +324,15 @@
handleChat();
};
recognition.onend = () => {
/* recognition.onend = () => {
micBtn.classList.remove('listening');
};
micBtn.addEventListener('click', () => {
recognition.start();
});
}); */
} else {
micBtn.style.display = 'none';
// micBtn.style.display = 'none';
}
// Resizing functionality
Loading