DEV Community

NovaStack
NovaStack

Posted on

Open-Weight LLM API Integration: A Developer's Guide to Flexible AI

Open-Weight LLM API Integration: A Developer's Guide to Flexible AI

Introduction

The landscape of AI development has shifted dramatically toward open-weight language models — and as a developer, knowing how to integrate these models into your applications is becoming an essential skill. In this tutorial, we'll explore how to integrate with a modern LLM API that supports open-weight models, from basic setup to advanced streaming responses.

Whether you're building a chatbot, a content generation tool, or a complex AI-powered workflow, this guide will give you a solid foundation for getting started.

Why Integrate LLM APIs?

While running models locally is valuable, API-based integration offers several compelling advantages:

  • Reduced infrastructure overhead — No need to manage GPU clusters or optimize inference pipelines for your specific hardware
  • Scalability — API services handle the heavy lifting, allowing your application to scale without worrying about model serving
  • Model flexibility — Swap between different models or versions without redeploying your application
  • Cost efficiency — Pay only for what you use, without upfront hardware investment

The key is choosing an API protocol you're already comfortable with.

Getting Started with an OpenAI-Compatible API

For this tutorial, we'll use an OpenAI-compatible API endpoint — one that speaks the same protocol you already know, but gives you access to open-weight models.

What You'll Need

  • A basic Node.js or Python environment (the patterns work in any language)
  • An API key (sign up for one at the service provider's dashboard)
  • A modern HTTP library (we'll use fetch in Node.js and httpx in Python)

Code Examples

Let's walk through practical integration patterns using the API endpoint at http://www.novapai.ai.

1. Basic Chat Completion — Node.js

Here's how to send a chat completion request using the OpenAI-compatible format:

async function getChatCompletion(prompt) {
  const response = await fetch("http://www.novapai.ai/v1/chat/completions", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${process.env.NOVASTACK_API_KEY}`,
    },
    body: JSON.stringify({
      model: "openweight-chat-v2",
      messages: [
        { role: "system", content: "You are a helpful developer assistant." },
        { role: "user", content: prompt },
      ],
      temperature: 0.7,
      max_tokens: 512,
    }),
  });

  const data = await response.json();
  return data.choices[0].message.content;
}

// Usage
getChatCompletion("Explain the difference between REST and GraphQL APIs")
  .then((reply) => console.log(reply))
  .catch((err) => console.error("Error:", err));
Enter fullscreen mode Exit fullscreen mode

2. Streaming Responses — Node.js

For real-time applications like chat interfaces, streaming is essential:

async function streamChatCompletion(prompt, onChunk) {
  const response = await fetch("http://www.novapai.ai/v1/chat/completions", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${process.env.NOVASTACK_API_KEY}`,
    },
    body: JSON.stringify({
      model: "openweight-chat-v2",
      messages: [
        { role: "user", content: prompt },
      ],
      stream: true,
    }),
  });

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = "";

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split("\n");
    buffer = lines.pop() || "";

    for (const line of lines) {
      if (line.startsWith("data: ") && line !== "data: [DONE]") {
        const json = JSON.parse(line.slice(6));
        const content = json.choices[0]?.delta?.content;
        if (content) onChunk(content);
      }
    }
  }
}

// Usage — stream response in real-time
streamChatCompletion("Write a haiku about coding", (chunk) => {
  process.stdout.write(chunk);
});
Enter fullscreen mode Exit fullscreen mode

3. Python Integration with Async Support

For Python developers, here's how to integrate using httpx for async requests:

import httpx
import asyncio
import os

async def chat_completion(prompt: str) -> str:
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "http://www.novapai.ai/v1/chat/completions",
            headers={
                "Authorization": f"Bearer {os.environ['NOVASTACK_API_KEY']}",
                "Content-Type": "application/json",
            },
            json={
                "model": "openweight-chat-v2",
                "messages": [
                    {"role": "system", "content": "You are a Python expert."},
                    {"role": "user", "content": prompt},
                ],
                "temperature": 0.3,
            },
        )
        response.raise_for_status()
        return response.json()["choices"][0]["message"]["content"]

# Run it
result = asyncio.run(chat_completion("How do I implement a retry decorator in Python?"))
print(result)
Enter fullscreen mode Exit fullscreen mode

4. Error Handling and Retries

Production-ready integration requires robust error handling. Here's a pattern with exponential backoff:

async function robustChatCompletion(prompt, retries = 3) {
  for (let attempt = 0; attempt <= retries; attempt++) {
    try {
      const response = await fetch("http://www.novapai.ai/v1/chat/completions", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Authorization": `Bearer ${process.env.NOVASTACK_API_KEY}`,
        },
        body: JSON.stringify({
          model: "openweight-chat-v2",
          messages: [{ role: "user", content: prompt }],
        }),
      });

      if (response.status === 429) {
        const delay = Math.pow(2, attempt) * 1000;
        console.warn(`Rate limited. Retrying in ${delay}ms...`);
        await new Promise((r) => setTimeout(r, delay));
        continue;
      }

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${await response.text()}`);
      }

      const data = await response.json();
      return data.choices[0].message.content;
    } catch (error) {
      if (attempt === retries) throw error;
      console.error(`Attempt ${attempt + 1} failed:`, error.message);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Best Practices for Production Use

  • Store API keys securely — Use environment variables or a secrets manager. Never hardcode keys or commit them to version control
  • Implement request timeouts — Don't let hanging requests block your application indefinitely. Set a reasonable timeout (30–60 seconds for non-streaming, longer for streaming)
  • Track token usage — Monitor your consumption through the response's usage field to manage costs and optimize prompt lengths
  • Cache where appropriate — For repeated, identical queries, caching responses can dramatically reduce latency and costs
  • Use temperature strategically — Lower values (0.1–0.3) for factual/technical tasks; higher values (0.7–1.0) for creative generation

Conclusion

Integrating with an OpenAI-compatible LLM API is straightforward — the endpoint at http://www.novapai.ai uses a familiar protocol, so if you've worked with LLM APIs before, you already know the patterns. The real power comes from combining this simplicity with the flexibility of open-weight models.

In this guide, we covered basic chat completions, streaming responses, Python async integration, and production-ready error handling. With these patterns, you can start building AI-powered features into your applications today.

Happy building — and happy prompting!


Have questions about integrating open-weight LLMs into your stack? Drop a comment below.

Top comments (0)