This page provides practical examples of how to use Basalt’s monitoring capabilities in common scenarios. These examples demonstrate different approaches to monitoring based on your specific use case.

Basic Prompt Monitoring

The simplest way to monitor AI interactions is with the basic monitoring approach when using Basalt-managed prompts:

// Get a prompt from Basalt (already includes monitoring)
const { value, generation } = await basalt.prompt.get('customer-reply', {
  variables: {
    customerName: 'John Smith',
    inquiry: 'When will my order arrive?'
  }
})

// Generate content with your LLM provider
const response = await generateWithLLM(value.text)

// Record the completion
generation.end(response)

Customer Support Workflow

This example monitors a customer support interaction with user identification:

async function handleCustomerQuery(user, query) {
  // Create a trace for the entire interaction
  const trace = basalt.monitor.createTrace('customer-support', {
    name: 'Customer Support Interaction',
    input: query,
    user: {
      id: user.id,
      name: user.name
    },
    organization: {
      id: user.companyId,
      name: user.companyName
    }
  })
  
  try {
    // Get the query classification prompt
    const { value: classifierPrompt, generation: classifyGeneration } = 
      await basalt.prompt.get('query-classifier')
    
    // Append the generation to our trace
    trace.append(classifyGeneration)
    
    // Classify the query
    const category = await classifyQuery(query, classifierPrompt.text)
    
    // Record the classification result
    classifyGeneration.end(category)
    
    // Create a response generation
    const responseLog = trace.createGeneration({
      name: 'generate-response',
      prompt: {
        slug: 'support-response',
        tag: category
      },
      input: query,
      variables: {
        query: query,
        category: category,
        userName: user.name
      }
    })
    
    // Generate the response
    const responseText = await generateResponse(query, category, user.name)
    
    // Record the response generation
    responseLog.end(responseText)
    
    // End the trace
    trace.end(responseText)
    
    return {
      category: category,
      response: responseText
    }
  } catch (error) {
    trace.update({
      metadata: {
        error: error.message
      }
    })
    trace.end(`Error: ${error.message}`)
    throw error
  }
}

Content Moderation

This example monitors content moderation with evaluation:

async function moderateUserContent(content) {
  // Create a trace for content moderation
  const trace = basalt.monitor.createTrace('content-moderation', {
    name: 'Content Moderation',
    input: content,
    evaluators: [
      { slug: 'content-policy' }
    ]
  })
  
  // Create a generation for moderation check
  const generation = trace.createGeneration({
    name: 'moderation-check',
    prompt: {
      slug: 'content-moderator'
    },
    input: content
  })
  
  try {
    // Check content with your moderation system
    const result = await checkContentModeration(content)
    const isSafe = result.includes('safe')
    
    // Record the moderation result with metadata
    generation.end({
      output: result,
      metadata: {
        isSafe: isSafe,
        contentType: 'text'
      }
    })
    
    // End the trace
    trace.end(result)
    
    return {
      isSafe: isSafe,
      result: result
    }
  } catch (error) {
    generation.end({
      output: `Error: ${error.message}`,
      metadata: {
        error: error.message
      }
    })
    trace.end(`Error: ${error.message}`)
    throw error
  }
}

Document Processing

This example tracks a simple document processing workflow:

async function processDocument(document) {
  // Create a trace for document processing
  const trace = basalt.monitor.createTrace('document-processing', {
    name: 'Document Processing',
    input: document.title,
    metadata: {
      documentId: document.id,
      documentType: document.type
    }
  })
  
  try {
    // Create a log for text extraction
    const extractionLog = trace.createLog({
      name: 'text-extraction',
      type: 'function',
      input: `Document: ${document.title}`
    })
    
    // Extract key information
    const extractedInfo = await extractDocumentInfo(document)
    
    // Record extraction
    extractionLog.end(extractedInfo)
    
    // Create a generation for summary
    const summaryGeneration = trace.createGeneration({
      name: 'document-summary',
      prompt: {
        slug: 'document-summarizer'
      },
      input: extractedInfo,
      variables: {
        documentType: document.type,
        maxLength: '250 words'
      }
    })
    
    // Generate summary
    const summaryText = await generateSummary(extractedInfo)
    
    // Record summary generation
    summaryGeneration.end(summaryText)
    
    // End trace
    trace.end(summaryText)
    
    return {
      extractedInfo: extractedInfo,
      summary: summaryText
    }
  } catch (error) {
    trace.update({
      metadata: {
        error: error.message,
        status: 'failed'
      }
    })
    
    trace.end(`Error: ${error.message}`)
    throw error
  }
}

RAG Application

This example tracks a simple Retrieval-Augmented Generation (RAG) application:

async function answerWithRAG(question) {
  // Create a trace for the RAG workflow
  const trace = basalt.monitor.createTrace('rag-query', {
    name: 'RAG Query Processing',
    input: question
  })
  
  try {
    // Create a log for retrieval
    const retrievalLog = trace.createLog({
      name: 'document-retrieval',
      type: 'retrieval',
      input: question
    })
    
    // Retrieve relevant documents
    const relevantDocs = await retrieveDocuments(question)
    
    // Record retrieval metrics
    retrievalLog.update({
      metadata: {
        documentCount: relevantDocs.length
      }
    })
    
    // Compile context from retrieved documents
    const context = combineDocuments(relevantDocs)
    retrievalLog.end(context)
    
    // Create a generation for answer
    const answerGeneration = trace.createGeneration({
      name: 'answer-generation',
      prompt: {
        slug: 'rag-answer-generator'
      },
      input: question,
      variables: {
        question: question,
        context: context
      }
    })
    
    // Generate answer using retrieved context
    const answerText = await generateAnswer(question, context)
    
    // Record answer generation
    answerGeneration.end(answerText)
    
    // End trace
    trace.end(answerText)
    
    return {
      answer: answerText,
      sources: relevantDocs.map(doc => doc.title)
    }
  } catch (error) {
    trace.update({
      metadata: {
        error: error.message
      }
    })
    trace.end(`Error: ${error.message}`)
    throw error
  }
}

Chat Interface

This example tracks a simple chat conversation:

async function processChatMessage(userId, sessionId, message, history) {
  // Create or get trace for this chat session
  let trace = sessionTraces[sessionId] || basalt.monitor.createTrace('chat-session', {
    name: 'Chat Conversation',
    input: message,
    user: { id: userId }
  })
  
  if (!sessionTraces[sessionId]) {
    sessionTraces[sessionId] = trace
  }
  
  // Create a log for this message exchange
  const turnLog = trace.createLog({
    name: `message-exchange`,
    type: 'span',
    input: message
  })
  
  try {
    // Create a generation for the assistant's response
    const responseGeneration = turnLog.createGeneration({
      name: 'assistant-response',
      prompt: { slug: 'chat-response' },
      variables: {
        userMessage: message,
        chatHistory: formatHistory(history)
      }
    })
    
    // Generate the response
    const responseText = await generateChatResponse(message, history)
    
    // Record the response
    responseGeneration.end(responseText)
    turnLog.end(responseText)
    
    // Add to history
    history.push({
      user: message,
      assistant: responseText
    })
    
    return responseText
  } catch (error) {
    turnLog.end(`Error: ${error.message}`)
    throw error
  }
}

// Storage for session traces
const sessionTraces = {}

These examples demonstrate different ways to use Basalt’s monitoring capabilities across various common use cases. You can adapt these patterns to your specific needs, combining approaches as needed.

For more complex scenarios, refer to the Tracing and Evaluations documentation.