Use this file to discover all available pages before exploring further.
Chatbots and virtual assistants powered by Infactory can answer specific questions about your data accurately and efficiently. This guide explains how to build chatbots that leverage Infactory’s data intelligence capabilities.
For a more conversational experience, you can combine Infactory with an LLM:
In this approach:
The LLM handles conversation flow and identifies when data questions are asked
Infactory answers specific data questions
The LLM formats the responses naturally
Backend (Node.js with OpenAI)
const express = require('express');const axios = require('axios');const { OpenAI } = require('openai');const router = express.Router();const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY});router.post('/api/chat', async (req, res) => { try { const { question, history } = req.body; // Step 1: Have the LLM determine if this is a data question const analysisPrompt = ` You are an assistant that helps determine if a question requires database querying. User question: "${question}" Is this a question that requires querying a database to answer correctly? Respond with YES if it's asking for specific data, statistics, or information that would be stored in a database. Respond with NO if it's a general question, chitchat, or something that doesn't require looking up specific data. Just respond with YES or NO.`; const analysisResponse = await openai.chat.completions.create({ model: "gpt-3.5-turbo", messages: [{ role: "user", content: analysisPrompt }], temperature: 0, }); const isDataQuestion = analysisResponse.choices[0].message.content.trim().startsWith('YES'); let responseData; if (isDataQuestion) { // Step 2: If it's a data question, query Infactory const infactoryResponse = await axios.post( 'https://api.infactory.ai/v1/query', { query: question, project_id: process.env.INFACTORY_PROJECT_ID, }, { headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.INFACTORY_API_KEY}` } } ); // Step 3: Have the LLM format the response const formattingPrompt = ` You are a helpful assistant. Format the following data into a natural, conversational response. User question: "${question}" Data: ${JSON.stringify(infactoryResponse.data)} Provide a conversational, easy to understand answer based strictly on this data.`; const formattingResponse = await openai.chat.completions.create({ model: "gpt-3.5-turbo", messages: [{ role: "user", content: formattingPrompt }], temperature: 0.7, }); responseData = { content: formattingResponse.choices[0].message.content, data: infactoryResponse.data.data, source: 'Infactory' }; } else { // Step 4: If it's not a data question, let the LLM handle it const chatMessages = [ { role: "system", content: "You are a helpful assistant that works with a database system. For data-specific questions, those are handled by another system. Focus on being helpful for general questions, clarifications, and conversation." }, ...history.map(msg => ({ role: msg.role, content: msg.content })), { role: "user", content: question } ]; const chatResponse = await openai.chat.completions.create({ model: "gpt-3.5-turbo", messages: chatMessages, temperature: 0.7, }); responseData = { content: chatResponse.choices[0].message.content, source: 'llm' }; } res.json(responseData); } catch (error) { console.error('Chatbot error:', error); res.status(500).json({ error: 'Failed to process your request' }); }});module.exports = router;
To handle follow-up questions, maintain conversation context and reference previous responses:
// Track the last query and its parameterslet lastQuery = null;// Example follow-up handlerfunction handleFollowup(question, history) { const lastMessage = history[history.length - 2]; // Get the last assistant message if (lastMessage && lastMessage.data && question.toLowerCase().includes('what about')) { // This looks like a follow-up question if (lastMessage.queryInfo.query_used === 'average_by_category') { // Extract what they're asking about const match = question.match(/what about (the |)([a-z0-9 ]+)/i); if (match) { const newCategory = match[2].trim(); // Update the parameters from the last query return { isFollowup: true, queryName: lastMessage.queryInfo.query_used, parameters: { ...lastMessage.queryInfo.parameters, category: newCategory } }; } } } return { isFollowup: false };}
To handle complex conversations with multiple turns:
// Conversation state managerclass ConversationState { constructor() { this.topics = new Map(); // Track topics mentioned in the conversation this.lastQuery = null; // Last executed query this.lastResponse = null; // Last response data this.context = {}; // Additional context like filters applied } updateFromMessage(message, isUser) { if (isUser) { // Process user message to extract topics, entities, etc. this.extractTopics(message); } else { // Update based on system response if (message.queryInfo) { this.lastQuery = message.queryInfo.query_used; this.lastResponse = message.data; // Update context based on the parameters used if (message.queryInfo.parameters) { Object.entries(message.queryInfo.parameters).forEach(([key, value]) => { this.context[key] = value; }); } } } } extractTopics(message) { // Simple implementation - in production you might use NLP services const lowerMessage = message.toLowerCase(); // Check for key topics relevant to your data domain const potentialTopics = ['sales', 'revenue', 'customers', 'products', 'regions']; potentialTopics.forEach(topic => { if (lowerMessage.includes(topic)) { // Increase the relevance score for this topic const currentScore = this.topics.get(topic) || 0; this.topics.set(topic, currentScore + 1); } }); } getRelevantContext(message) { // Determine what context is relevant to the current message const context = { ...this.context }; // Decay or remove irrelevant context based on the new message // This is highly domain-specific return context; }}
Challenge: Users ask questions that could match multiple queries or have unclear parameters.Solution: Implement a clarification flow where the chatbot asks follow-up questions when a question is ambiguous. For example:
if (matchingQueries.length > 1 && matchingQueries[0].confidence < 0.8) { return { needsClarification: true, clarificationQuestion: `I'm not sure exactly what you're asking about. Are you interested in ${matchingQueries.map(q => q.topic).join(' or ')}?`, matchingQueries: matchingQueries };}
Maintaining Conversation Context
Challenge: Keeping track of context across multiple turns of conversation.Solution: Implement a context management system that tracks entities, topics, and previous queries. Use this context to enhance subsequent queries.
// Update context based on the current queryfunction updateContext(context, query, parameters) { return { ...context, lastQuery: query, entities: { ...context.entities, ...extractEntities(parameters) }, timestamp: Date.now() };}// Apply context to a new questionfunction applyContext(question, context) { // If the question includes pronouns like "it", "them", "those", // try to resolve using context if (/\b(it|them|those|that|these)\b/i.test(question)) { if (context.entities.category) { // Replace pronouns with the actual entity from context return question.replace( /\b(it|them|those|that|these)\b/i, context.entities.category ); } } return question;}
Unrealistic User Expectations
Challenge: Users expect the chatbot to answer any question, regardless of whether the data supports it.Solution: Set clear expectations and provide informative responses about the chatbot’s capabilities:
function handleUnanswerable(question) { // Check if the question is about a topic we don't have data for const unsupportedTopics = ['employee salaries', 'future predictions', 'competitor data']; for (const topic of unsupportedTopics) { if (question.toLowerCase().includes(topic)) { return `I don't have information about ${topic}. I can help you with questions about our sales, customers, products, and regional performance.`; } } // General fallback return "I don't have enough information to answer that question. I can help you with questions about our business data such as sales figures, customer metrics, and product performance.";}