Zeldafan NPM Package Usage Guide - Haidra-Org/AI-Horde GitHub Wiki

This guide walks you through the process of using the zeldafan NPM package to interact with the AI Horde API. It covers installation and setup for image generation. You'll learn how to prepare generation payloads, post requests, check generation status, and retrieve results so you can integrate the AI-Horde into your app.

Installation and Setup

  1. Install the package:

    npm install @zeldafan0225/ai_horde
    
  2. Import the AIHorde class:

    const { AIHorde } = require("@zeldafan0225/ai_horde");
    
  3. Initialize the AIHorde instance:

    const ai_horde = new AIHorde({
      cache_interval: 1000 * 10, // Cache refresh interval in milliseconds
      cache: {
        generations_check: 1000 * 30, // Cache duration for generation checks
      },
      client_agent: "My-Project:v0.0.1:My-Contact", // Identify your application
      default_token: "yourAiHordeApiKey" // Optional: Your API key for priority queue
    });
    

    Note: The default_token is only needed if you want to use your API key to spend kudos for queue priority or if you have a service account. If you don't set one, the default anonymous token will be used instead.

    Client Agent: Include a client agent in the form of application_name:v0.0.0:your_contact_info. If you're in the AI-Horde discord, your contact info could be @your_handle on discord. Otherwise, please use an email.

Image Generation

Preparing the Generation Payload

The generation payload is a crucial part of your request. It defines what kind of image you want to generate and how. Here's an example with explanations:

const generationDataPayload = {
  prompt: "A serene landscape with mountains and a lake",
  nsfw: false,
  models: ["AlbedoBase XL (SDXL)"], // Choose from models at https://tinybots.net/artbot/info/models
  params: {
    height: 1024, // Must be divisible by 64
    width: 1024,  // Must be divisible by 64
    n: 1,         // Number of images to generate (up to 4 for Discord bots)
    steps: 30,
    cfg_scale: 6,
    sampler: "k_dpmpp_2m",
    karras: true,
  }
};

Key points about the payload:

  • You can use any of the models found on https://tinybots.net/artbot/info/models. Just copy and paste the name of the model, like "AlbedoBase XL (SDXL)".
  • The width and height should be divisible by 64 for optimal results.
  • n is the number of images to generate. For Discord bots, you can generate up to 4 images at a time.
  • You can check what other parameters you can include from the aihorde.net api docs

Posting the Generation Request

When you post your request, you'll receive a generation ID. This ID is crucial for checking the status and retrieving results later.

async function generateImage() {
  try {
    const response = await ai_horde.postAsyncImageGenerate(generationDataPayload);
    const generationId = response.id;
    return generationId;
  } catch (error) {
    console.error("Error posting generation request:", error);
    throw error;
  }
}

Checking Generation Status

The generation process can take some time. You'll need to periodically check the status until it's complete.

async function checkGenerationStatus(generationId) {
  try {
    let status;
    do {
      status = await ai_horde.getImageGenerationCheck(generationId);
      console.log(`Job ${generationId} progress: ${status.finished}/${status.processing + status.waiting + status.finished}`);
      await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds before checking again
    } while (status.done === false);
    
    return status;
  } catch (error) {
    console.error("Error checking generation status:", error);
    throw error;
  }
}

You can also check the status manually in your browser by visiting https://aihorde.net/api/v2/generate/status/[generationId]. This can be helpful for debugging or understanding the response structure.

Retrieving Generation Results

Once the generation is complete, you can retrieve the results:

async function getGenerationResults(generationId) {
  try {
    const finishedData = await ai_horde.getImageGenerationStatus(generationId);
    return finishedData.generations;
  } catch (error) {
    console.error("Error retrieving generation results:", error);
    throw error;
  }
}

The main difference between getImageGenerationCheck and getImageGenerationStatus is that check won't have the finished image results, but status will. For text generation (Kobold AI), both methods will return the results.

Important: The status endpoint has a much more strict rate limit than the check endpoint. You should wait for the generation to be complete (or at least one image complete, in the case of multiple images requested) before you begin polling the status endpoint.

Data Options We Can Get From getImageGenerationStatus

If you want to see information such as the image result, or meta data, such as weather or not the image was censored, there are a lot of options on the status page to choose from. You can check with the link https://aihorde.net/api/v2/generate/status/[generationId] for the names of the options you can get data from. Here is an example of getting the meta data to see if an image was censored for nsfw

    const genImageData = finishedData.generations[0];  // on the status page it will say in the parent options 'generations' then the first image will be under [0], its formatted like an array
    const metadataItem = genImageData.gen_metadata[0];  // you'll see this nestled under generations > [0] > gen_metadata > [0] as an array of options, it will say if an image was censored or not in 'type'

    if (metadataItem && metadataItem.type.includes('censorship')) {
      console.log("The generated image was censored.");
    } 

Putting It All Together

Now, let's see how all these pieces fit together in a complete example:

const { AIHorde } = require("@zeldafan0225/ai_horde");

const ai_horde = new AIHorde({
  cache_interval: 1000 * 10,
  cache: {
    generations_check: 1000 * 30,
  },
  client_agent: "My-Project:v0.0.1:My-Contact",
  default_token: "yourAiHordeApiKey"  
});

const generationDataPayload = {
  prompt: "A serene landscape with mountains and a lake",
  nsfw: false,
  models: ["AlbedoBase XL (SDXL)"],
  params: {
    height: 1024, 
    width: 1024,
    n: 1,  // for Discord bots, you can generate up to 4 images at a time
    steps: 30,
    cfg_scale: 6,
    sampler: "k_dpmpp_2m",
    karras: true,
  }
};

async function generateAndRetrieveImage() {
  try {
    // Post the generation request
    const response = await ai_horde.postAsyncImageGenerate(generationDataPayload); 
    const generationId = response.id;

    // Check the generation status
    let status = await ai_horde.getImageGenerationCheck(generationId);

    while (status.finished !== status.processing + status.waiting + status.finished) {
      status = await ai_horde.getImageGenerationCheck(generationId);
      const waitTime = 20;
      console.log(`Job ${generationId} not done yet. Checking again in ${waitTime} seconds...`);
      await new Promise(resolve => setTimeout(resolve, waitTime * 1000));
    }

    // Retrieve the finished data
    const finishedData = await ai_horde.getImageGenerationStatus(generationId);

    // Process the results
    const genImageData = finishedData.generations[0]; 
    const metadataItem = genImageData.gen_metadata[0];

    if (metadataItem && metadataItem.type.includes('censorship')) {
      console.log("The generated image was censored.");
    } 

    // Here's how you might reply in a Discord bot context
    // await interaction.reply({ content: `Generated using model: ${generationDataPayload.models[0]}`, files: [{ attachment: genImageData.img }] });
    
    console.log("Generation complete. Image URL:", genImageData.img);
    return genImageData;
  } catch (error) {
    console.error("An error occurred during image generation:", error);
    throw error;
  }
}

generateAndRetrieveImage().then(result => {
  console.log("Generation successful!");
}).catch(error => {
  console.error("Generation failed:", error);
});

This example demonstrates the entire process:

  1. Setting up the AI Horde instance
  2. Preparing the generation payload
  3. Posting the generation request
  4. Checking the generation status in a loop
  5. Retrieving the finished data
  6. Processing the results, including checking for censorship
  7. Logging the result or replying in a Discord context

Note that this example uses a while loop to check the status repeatedly. In a production environment, you might want to implement a more sophisticated approach, such as exponential backoff, to avoid unnecessary API calls.

Also, remember to handle the API key securely in your actual implementation. Don't hardcode it as shown in this example.

Best Practices

  1. Rate Limiting: Respect the AI Horde's rate limits to avoid being flagged as a malicious actor. Check the headers on any response for rate limit information.
  2. Error Handling: Always wrap API calls in try-catch blocks to handle potential errors gracefully.
  3. API Key Security: Never hardcode your API key in your application. Use environment variables or secure key management solutions.
  4. Model Selection: Choose appropriate models for your use case. Some models may be better suited for certain types of generations.

Troubleshooting

  1. API Key Issues:

    • If you're having trouble with your API key, ensure it's correctly set in the AIHorde constructor
    • Verify that you have sufficient kudos for your requests
  2. Generation Not Starting:

    • Double-check your payload format, especially the model name and parameters
    • Ensure you're not exceeding rate limits or usage quotas
  3. Unexpected Results:

    • If images are censored unexpectedly, check the gen_metadata for 'censored' or other flags
    • Verify that your prompt adheres to the AI Horde's content policies
  4. Performance Issues:

    • If generations are taking too long, consider using models with faster inference times or with more workers
  5. Debugging Tips:

    • You can manually check the status of a generation by visiting https://aihorde.net/api/v2/generate/status/[generationId] in your browser
    • Use console logging liberally to track the progress of your requests and identify where issues might be occurring
  6. Discord Bot Specific:

    • When using the AI Horde with a Discord bot, remember to use deferReply() before starting a long-running generation process
    • Use editReply() to post results once the generation is complete

Remember, if you encounter persistent issues or need further clarification, consult the official AI Horde API documentation or reach out to the AI Horde community for support.

For more detailed information on API endpoints and parameters, refer to the official AI Horde API documentation.

Remember to always stay updated with the latest version of the NPM package and the AI Horde API, as features and endpoints may change over time.