Skip to content

Node.js SDK: Text Generation

This guide covers the text generation capabilities of the PaiTIENT Secure Model Service Node.js SDK, allowing you to securely generate text from deployed models in a HIPAA/SOC2 compliant environment.

Basic Text Generation

Generate text from a deployed model:

javascript
const { PaiTIENTClient } = require('paitient-secure-model');

// Initialize client
const client = new PaiTIENTClient({
  apiKey: process.env.PAITIENT_API_KEY,
  clientId: process.env.PAITIENT_CLIENT_ID
});

// Generate text
async function generateText() {
  try {
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: "What are the potential side effects of metformin?"
    });

    console.log(response.text);
  } catch (error) {
    console.error('Generation failed:', error);
  }
}

generateText();

Generation Options

Text Parameters

Customize text generation with various parameters:

javascript
// Generation with parameters
const response = await client.generateText({
  deploymentId: "dep_12345abcde",
  prompt: "What are the potential side effects of metformin?",
  maxTokens: 500,              // Maximum length of the generated text
  temperature: 0.7,             // Controls randomness (0.0-1.0)
  topP: 0.95,                  // Nucleus sampling parameter
  topK: 50,                    // Top-k sampling parameter
  stop: ["\n\n", "END"],        // Stop sequences
  repetitionPenalty: 1.1,      // Penalize repeated tokens
  presencePenalty: 0.0,        // Penalize tokens based on presence
  frequencyPenalty: 0.0        // Penalize tokens based on frequency
});

System Messages

Use system messages to control the model's behavior:

javascript
// Generation with system message
const response = await client.generateText({
  deploymentId: "dep_12345abcde",
  prompt: "What are the potential side effects of metformin?",
  systemMessage: "You are a helpful medical assistant providing accurate information to healthcare professionals. Always include references to clinical guidelines and mention important warnings."
});

Context Management

Maintain conversation context:

javascript
// Conversation with context
const conversation = client.createConversation({ deploymentId: "dep_12345abcde" });

// First message
const response1 = await conversation.generateText({
  prompt: "What are the potential side effects of metformin?"
});
console.log("Response 1:", response1.text);

// Follow-up question (context is automatically maintained)
const response2 = await conversation.generateText({
  prompt: "What about patients with kidney disease?"
});
console.log("Response 2:", response2.text);

// Another follow-up
const response3 = await conversation.generateText({
  prompt: "Are there any alternatives for these patients?"
});
console.log("Response 3:", response3.text);

Advanced Generation Features

Streaming Responses

Stream the response as it's generated:

javascript
// Stream the response
const stream = await client.generateTextStream({
  deploymentId: "dep_12345abcde",
  prompt: "Write a detailed summary of diabetes management techniques.",
  maxTokens: 1000
});

// Handle the stream with event listeners
stream.on('data', (chunk) => {
  process.stdout.write(chunk.text);
});

stream.on('end', () => {
  console.log('\nGeneration complete');
});

stream.on('error', (error) => {
  console.error('Stream error:', error);
});

// Alternative using async iteration
try {
  for await (const chunk of stream) {
    process.stdout.write(chunk.text);
  }
  console.log('\nGeneration complete');
} catch (error) {
  console.error('Stream error:', error);
}

Batch Processing

Process multiple prompts efficiently:

javascript
// Define a list of prompts
const prompts = [
  "What are the symptoms of hypertension?",
  "What are common treatments for type 2 diabetes?",
  "Explain the mechanism of action for statins."
];

// Process in batch
async function batchGenerate() {
  try {
    const results = await client.generateTextBatch({
      deploymentId: "dep_12345abcde",
      prompts: prompts,
      maxTokens: 300
    });

    results.forEach((result, i) => {
      console.log(`Prompt ${i+1}: ${prompts[i]}`);
      console.log(`Response: ${result.text}`);
      console.log();
    });
  } catch (error) {
    console.error('Batch generation failed:', error);
  }
}

batchGenerate();

Function Calling

Define functions that the model can call:

javascript
const { PaiTIENTClient, FunctionDefinition } = require('paitient-secure-model');

// Initialize client
const client = new PaiTIENTClient({
  apiKey: process.env.PAITIENT_API_KEY,
  clientId: process.env.PAITIENT_CLIENT_ID
});

async function functionCallingExample() {
  try {
    // Define functions
    const functions = [
      new FunctionDefinition({
        name: "search_medication_interactions",
        description: "Search for potential interactions between medications",
        parameters: {
          type: "object",
          properties: {
            medications: {
              type: "array",
              items: { type: "string" },
              description: "List of medications to check for interactions"
            }
          },
          required: ["medications"]
        }
      }),
      new FunctionDefinition({
        name: "calculate_dosage",
        description: "Calculate medication dosage based on patient parameters",
        parameters: {
          type: "object",
          properties: {
            medication: { type: "string", description: "Medication name" },
            weight_kg: { type: "number", description: "Patient weight in kg" },
            age_years: { type: "number", description: "Patient age in years" },
            kidney_function: { type: "string", description: "Kidney function (normal, impaired, severe)" }
          },
          required: ["medication", "weight_kg", "age_years"]
        }
      })
    ];

    // Generate text with function calling
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: "Check for interactions between metformin, lisinopril, and simvastatin.",
      functions: functions,
      functionCall: "auto"  // Options: "auto", "none", or {name: "specific_function"}
    });

    // Check if the model decided to call a function
    if (response.functionCall) {
      const functionName = response.functionCall.name;
      const functionArgs = response.functionCall.arguments;
      
      console.log(`Model called function: ${functionName}`);
      console.log(`Arguments: ${JSON.stringify(functionArgs, null, 2)}`);
      
      // Here you would actually execute the function with the provided arguments
      // and then potentially continue the conversation with the result
      if (functionName === "search_medication_interactions") {
        // Simulate function execution
        const result = {
          interactions: [
            {medications: ["metformin", "lisinopril"], severity: "low", description: "..."},
            {medications: ["metformin", "simvastatin"], severity: "moderate", description: "..."}
          ]
        };
        
        // Continue the conversation with the function result
        const followUp = await client.generateText({
          deploymentId: "dep_12345abcde",
          prompt: "What should I do about these interactions?",
          functionResults: [{
            name: functionName,
            arguments: functionArgs,
            result: result
          }]
        });
        
        console.log("Follow-up:", followUp.text);
      }
    } else {
      console.log("Model response:", response.text);
    }
  } catch (error) {
    console.error('Function calling example failed:', error);
  }
}

functionCallingExample();

Security Controls

Apply security controls to text generation:

javascript
const { PaiTIENTClient, Security } = require('paitient-secure-model');

// Initialize client
const client = new PaiTIENTClient({
  apiKey: process.env.PAITIENT_API_KEY,
  clientId: process.env.PAITIENT_CLIENT_ID
});

async function secureGeneration() {
  try {
    // Generate text with security controls
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: "Patient with diabetes and hypertension, currently taking metformin and lisinopril.",
      securitySettings: new Security.SecuritySettings({
        dataFiltering: new Security.DataFiltering({
          detectPii: true,           // Detect personally identifiable information
          redactPhi: true,           // Redact protected health information
          contentFiltering: "strict", // Apply strict content filtering
          detectToxicContent: true    // Detect potentially harmful content
        })
      })
    });
    
    console.log("Secure response:", response.text);
  } catch (error) {
    console.error('Secure generation failed:', error);
  }
}

secureGeneration();

Response Analysis

Response Metadata

Access additional information about the generation:

javascript
// Analyze response metadata
async function analyzeMetadata() {
  try {
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: "What are the potential side effects of metformin?",
      maxTokens: 500,
      returnMetadata: true
    });

    console.log("Response:", response.text);
    console.log("Token count:", response.usage.totalTokens);
    console.log("Prompt tokens:", response.usage.promptTokens);
    console.log("Completion tokens:", response.usage.completionTokens);
    console.log("Finish reason:", response.finishReason);
    console.log("Model used:", response.model);
    console.log("Created at:", response.createdAt);
  } catch (error) {
    console.error('Metadata analysis failed:', error);
  }
}

analyzeMetadata();

Content Analysis

Analyze the generated content:

javascript
// Analyze generated content
async function analyzeContent() {
  try {
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: "What are the potential side effects of metformin?"
    });
    
    const analysis = await client.analyzeText({
      text: response.text,
      analyses: ["toxicity", "factuality", "bias", "medicalAccuracy"]
    });

    console.log("Toxicity score:", analysis.toxicity);
    console.log("Factuality score:", analysis.factuality);
    console.log("Bias score:", analysis.bias);
    console.log("Medical accuracy score:", analysis.medicalAccuracy);
  } catch (error) {
    console.error('Content analysis failed:', error);
  }
}

analyzeContent();

Generation Control

Rate Limiting

Implement rate limiting for your application:

javascript
const { PaiTIENTClient, RateLimiter } = require('paitient-secure-model');

// Initialize client
const client = new PaiTIENTClient({
  apiKey: process.env.PAITIENT_API_KEY,
  clientId: process.env.PAITIENT_CLIENT_ID
});

async function rateLimitedGeneration() {
  // Initialize rate limiter
  const limiter = new RateLimiter({
    requestsPerMinute: 60,
    burstSize: 10
  });

  // Generate text with rate limiting
  try {
    // Acquire a token from the rate limiter
    await limiter.acquire();
    
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: "What are the potential side effects of metformin?"
    });
    
    console.log(response.text);
  } catch (error) {
    if (error.name === 'RateLimitError') {
      console.error(`Rate limit exceeded: ${error.message}`);
    } else {
      console.error(`Generation failed: ${error.message}`);
    }
  }
}

rateLimitedGeneration();

Timeout Control

Control timeouts for requests:

javascript
// Generate text with timeout control
async function timeoutControlledGeneration() {
  try {
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: "Write a detailed analysis of current diabetes management guidelines.",
      maxTokens: 2000,
      timeout: 30000  // Timeout in milliseconds (30 seconds)
    });
    
    console.log(response.text);
  } catch (error) {
    if (error.name === 'TimeoutError') {
      console.error("Request timed out. Try again with fewer tokens or simpler prompt.");
    } else {
      console.error(`Generation failed: ${error.message}`);
    }
  }
}

timeoutControlledGeneration();

Advanced Usage

Async/Promise Handling

Handle multiple operations with proper Promise handling:

javascript
// Sequential processing of multiple prompts
async function processSequentially() {
  const prompts = [
    "What are the symptoms of hypertension?",
    "What are common treatments for type 2 diabetes?",
    "Explain the mechanism of action for statins."
  ];
  
  try {
    // Process prompts sequentially
    for (const prompt of prompts) {
      console.log(`Processing: ${prompt}`);
      const response = await client.generateText({
        deploymentId: "dep_12345abcde",
        prompt: prompt,
        maxTokens: 300
      });
      
      console.log(`Response: ${response.text}\n`);
    }
  } catch (error) {
    console.error(`Processing failed: ${error.message}`);
  }
}

// Parallel processing of multiple prompts
async function processInParallel() {
  const prompts = [
    "What are the symptoms of hypertension?",
    "What are common treatments for type 2 diabetes?",
    "Explain the mechanism of action for statins."
  ];
  
  try {
    // Create an array of promises
    const promises = prompts.map(prompt => 
      client.generateText({
        deploymentId: "dep_12345abcde",
        prompt: prompt,
        maxTokens: 300
      })
    );
    
    // Wait for all promises to resolve
    const responses = await Promise.all(promises);
    
    // Process the results
    responses.forEach((response, index) => {
      console.log(`Prompt: ${prompts[index]}`);
      console.log(`Response: ${response.text}\n`);
    });
  } catch (error) {
    console.error(`Parallel processing failed: ${error.message}`);
  }
}

Custom Models

Generate text from custom fine-tuned models:

javascript
async function useFineTunedModel() {
  try {
    // Get fine-tuned model ID
    const fineTuningJob = await client.getFineTuningJob("ft_12345abcde");
    const fineTunedModel = fineTuningJob.fineTunedModel;

    // Deploy the fine-tuned model
    const deployment = await client.createDeployment({
      modelName: fineTunedModel,
      deploymentName: "custom-medical-assistant"
    });

    // Wait for deployment to complete
    await deployment.waitUntilReady();

    // Generate text from custom model
    const response = await client.generateText({
      deploymentId: deployment.id,
      prompt: "What are the potential side effects of metformin?"
    });

    console.log(response.text);
  } catch (error) {
    console.error(`Custom model usage failed: ${error.message}`);
  }
}

useFineTunedModel();

Multi-tenant Usage

For applications serving multiple clients:

javascript
// Generate text in multi-tenant context
async function multiTenantGeneration() {
  try {
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: "What are the potential side effects of metformin?",
      tenantId: "tenant_12345",  // Ensures strong isolation
      userId: "user_67890"       // For audit and attribution
    });
    
    console.log(response.text);
  } catch (error) {
    console.error(`Multi-tenant generation failed: ${error.message}`);
  }
}

multiTenantGeneration();

Error Handling

Implement robust error handling:

javascript
const { PaiTIENTClient, errors } = require('paitient-secure-model');

const client = new PaiTIENTClient({
  apiKey: process.env.PAITIENT_API_KEY,
  clientId: process.env.PAITIENT_CLIENT_ID
});

async function robustErrorHandling() {
  try {
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: "What are the potential side effects of metformin?",
      maxTokens: 500
    });
    
    console.log(response.text);
  } catch (error) {
    if (error instanceof errors.ResourceNotFoundError) {
      console.error("Deployment not found. Check your deployment ID.");
    } else if (error instanceof errors.RateLimitError) {
      console.error(`Rate limit exceeded. Retry after ${error.retryAfter} seconds.`);
    } else if (error instanceof errors.ContentFilterError) {
      console.error(`Content filtered: ${error.reason}`);
    } else if (error instanceof errors.InvalidParameterError) {
      console.error(`Invalid parameter: ${error.message}`);
    } else if (error instanceof errors.GenerationError) {
      console.error(`Generation failed: ${error.message}`);
      console.error(`Request ID for troubleshooting: ${error.requestId}`);
    } else {
      console.error(`Unexpected error: ${error.message}`);
    }
  }
}

robustErrorHandling();

Best Practices

Prompt Engineering

Follow these best practices for effective prompts:

  1. Be Specific: Provide clear, detailed instructions
  2. Establish Context: Include relevant background information
  3. Structure Output: Specify desired format and structure
  4. Use Examples: Include examples for complex tasks
  5. Iterate: Refine prompts based on results

Example of a well-structured prompt:

javascript
const prompt = `
You are a clinical assistant helping a healthcare provider. 
Provide information about metformin for diabetes management.

Please include:
1. Common side effects and their frequency
2. Contraindications
3. Recommended dosage adjustments for patients with renal impairment
4. Drug interactions to be aware of

Format the response with clear headings and bullet points.
Cite relevant clinical guidelines where appropriate.
`;

const response = await client.generateText({
  deploymentId: "dep_12345abcde",
  prompt: prompt,
  maxTokens: 800
});

Performance Optimization

Optimize text generation performance:

  1. Batch Requests: Use batch API for multiple prompts
  2. Stream Long Responses: Use streaming for better UX
  3. Optimize Tokens: Keep prompts concise
  4. Cache Common Responses: Implement response caching
  5. Right-size Parameters: Adjust maxTokens to actual needs
javascript
// Example of response caching
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 3600 });  // Cache for 1 hour

async function cachedGeneration(prompt) {
  // Create a cache key
  const cacheKey = `${prompt}-dep_12345abcde`;
  
  // Check if response is cached
  const cachedResponse = cache.get(cacheKey);
  if (cachedResponse) {
    console.log("Using cached response");
    return cachedResponse;
  }
  
  // Generate new response
  const response = await client.generateText({
    deploymentId: "dep_12345abcde",
    prompt: prompt,
    maxTokens: 500
  });
  
  // Cache the response
  cache.set(cacheKey, response);
  
  return response;
}

Security

Ensure secure text generation:

  1. Sanitize Inputs: Validate and clean user inputs
  2. Enable Content Filtering: Prevent harmful outputs
  3. Use PII/PHI Detection: Protect sensitive information
  4. Audit Generations: Track and review outputs
  5. Implement Rate Limiting: Prevent abuse
javascript
// Example of input sanitization
function sanitizeInput(input) {
  if (!input || typeof input !== 'string') {
    throw new Error('Input must be a non-empty string');
  }
  
  // Trim excess whitespace
  let sanitized = input.trim();
  
  // Check length
  if (sanitized.length > 4000) {
    sanitized = sanitized.substring(0, 4000);
  }
  
  // Check for potentially harmful patterns
  const harmfulPatterns = ['<script>', 'exec(', 'system('];
  for (const pattern of harmfulPatterns) {
    if (sanitized.toLowerCase().includes(pattern)) {
      throw new Error('Input contains potentially harmful content');
    }
  }
  
  return sanitized;
}

async function securePromptHandling(userInput) {
  try {
    // Sanitize user input
    const sanitizedPrompt = sanitizeInput(userInput);
    
    // Generate text with security settings
    const response = await client.generateText({
      deploymentId: "dep_12345abcde",
      prompt: sanitizedPrompt,
      securitySettings: new Security.SecuritySettings({
        dataFiltering: new Security.DataFiltering({
          detectPii: true,
          redactPhi: true,
          contentFiltering: "strict"
        })
      })
    });
    
    return response;
  } catch (error) {
    console.error(`Secure handling failed: ${error.message}`);
    return { text: "Sorry, I couldn't process that request safely." };
  }
}

Next Steps

Released under the MIT License.