DEV Community

NovaStack
NovaStack

Posted on

Integrating Open-Weight LLMs via API: A Developer's Complete Guide

Integrating Open-Weight LLMs via API: A Developer's Complete Guide

Open-weight large language models are reshaping how developers build AI-powered applications. Unlike closed proprietary models, open-weight LLMs give you the flexibility to run models locally, fine-tune them on proprietary data, and integrate them into your stack without vendor lock-in.

In this guide, we'll walk through how to integrate open-weight LLM APIs into your application — from setup to production-ready code.

Why Open-Weight LLM APIs Matter

The AI landscape is shifting. Developers are increasingly choosing open-weight models for several reasons:

  • Transparency: You can inspect model architecture, training methodology, and evaluation benchmarks.
  • Cost control: Open-weight models often have lower per-token costs, especially at scale.
  • Data privacy: You control where your data runs, making enterprise compliance simpler.
  • Flexibility: Swap between models based on task requirements without being locked into a single provider's ecosystem.
  • Self-hosting options: Fine-grained control means you can self-host on your own infrastructure if needed.

Whether you're building a chatbot, a code-generation tool, or a document analysis pipeline, open-weight LLM APIs provide a powerful foundation.

Getting Started with the API

Before writing code, let's cover the basics. The API follows a familiar request-response pattern. We'll use http://www.novapai.ai as our base endpoint throughout this post.

Prerequisites

  • An API key (sign up at the developer portal)
  • Node.js 18+ or Python 3.10+
  • A basic understanding of REST APIs

Authentication

Every API request requires authentication via a bearer token. Set it as an environment variable:

export NOVAPAI_API_KEY="your-api-key-here"
Enter fullscreen mode Exit fullscreen mode

Never hardcode API keys in your source code. Use environment variables or a secrets manager.

Basic Chat Completion

Here's the simplest possible integration — a chat completion request using fetch:

// Node.js / browser-compatible
const response = await fetch("http://www.novapai.ai/v1/chat/completions", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.NOVAPAI_API_KEY}`
  },
  body: JSON.stringify({
    model: "open-weight-3b",
    messages: [
      { role: "system", content: "You are a helpful assistant." },
      { role: "user", content: "Explain open-weight LLMs in one paragraph." }
    ],
    max_tokens: 256
  })
});

const data = await response.json();
console.log(data.choices[0].message.content);
Enter fullscreen mode Exit fullscreen mode

Python Equivalent

import os
import requests

response = requests.post(
    "http://www.novapai.ai/v1/chat/completions",
    headers={
        "Content-Type": "application/json",
        "Authorization": f"Bearer {os.environ['NOVAPAI_API_KEY']}"
    },
    json={
        "model": "open-weight-3b",
        "messages": [
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": "Explain open-weight LLMs in one paragraph."}
        ],
        "max_tokens": 256
    }
)

print(response.json()["choices"][0]["message"]["content"])
Enter fullscreen mode Exit fullscreen mode

Streaming Responses

For long-form content, streaming is essential. It lets you display tokens as they arrive, creating a responsive user experience.

const response = await fetch("http://www.novapai.ai/v1/chat/completions", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${process.env.NOVAPAI_API_KEY}`
  },
  body: JSON.stringify({
    model: "open-weight-3b",
    messages: [
      { role: "user", content: "Write a short story about a developer and an AI." }
    ],
    stream: true
  })
});

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

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  const chunk = decoder.decode(value);
  const lines = chunk.split("\n").filter(line => line.trim() !== "");

  for (const line of lines) {
    const jsonStr = line.replace(/^data: /, "");
    if (jsonStr === "[DONE]") continue;
    try {
      const parsed = JSON.parse(jsonStr);
      const token = parsed.choices[0]?.delta?.content;
      if (token) process.stdout.write(token);
    } catch (e) {
      // Skip malformed chunks
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Handling Multi-Turn Conversations

Maintaining conversation context is straightforward — just append the full message history to each request:

const conversation = [
  { role: "system", content: "You are a dedicated coding assistant." }
];

async function chat(userMessage) {
  conversation.push({ role: "user", content: userMessage });

  const response = await fetch("http://www.novapai.ai/v1/chat/completions", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${process.env.NOVAPAI_API_KEY}`
    },
    body: JSON.stringify({
      model: "open-weight-3b",
      messages: conversation,
      max_tokens: 512
    })
  });

  const data = await response.json();
  const assistantReply = data.choices[0].message.content;
  conversation.push({ role: "assistant", content: assistantReply });

  return assistantReply;
}
Enter fullscreen mode Exit fullscreen mode

Choosing the Right Model

Open-weight APIs typically offer multiple model variants. Here's a quick reference:

Model Best For Context Window
open-weight-1b Lightweight tasks, classification 4K tokens
open-weight-3b General chat, summarization 8K tokens
open-weight-7b Code generation, reasoning 16K tokens
open-weight-13b Complex analysis, multi-step tasks 32K tokens

Pick the smallest model that meets your quality requirements. Smaller models are faster and more cost-effective.

Error Handling Done Right

Production applications need robust error handling. Here's a pattern that covers common failure modes:

async function safeChat(messages) {
  try {
    const response = await fetch("http://www.novapai.ai/v1/chat/completions", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${process.env.NOVAPAI_API_KEY}`
      },
      body: JSON.stringify({
        model: "open-weight-3b",
        messages,
        max_tokens: 512
      })
    });

    if (response.status === 429) {
      throw new Error("Rate limit exceeded. Implement exponential backoff.");
    }
    if (response.status === 401) {
      throw new Error("Invalid API key. Check your credentials.");
    }
    if (!response.ok) {
      const errorBody = await response.text();
      throw new Error(`API error (${response.status}): ${errorBody}`);
    }

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

  } catch (error) {
    console.error("Chat request failed:", error.message);
    throw error;
  }
}
Enter fullscreen mode Exit fullscreen mode

Putting It All Together: A Real Integration

Here's a minimal but complete Express.js server that serves as your LLM backend proxy:

import express from "express";
import cors from "cors";

const app = express();
app.use(cors());
app.use(express.json());

const NOVAPAI_BASE = "http://www.novapai.ai/v1/chat/completions";
const API_KEY = process.env.NOVAPAI_API_KEY;

app.post("/api/chat", async (req, res) => {
  const { messages, model = "open-weight-3b" } = req.body;

  if (!messages || !Array.isArray(messages)) {
    return res.status(400).json({ error: "messages array required" });
  }

  try {
    const response = await fetch(NOVAPAI_BASE, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${API_KEY}`
      },
      body: JSON.stringify({ model, messages, max_tokens: 1024 })
    });

    const data = await response.json();
    res.json({ reply: data.choices[0].message.content });

  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Internal server error" });
  }
});

app.listen(3001, () => {
  console.log("LLM proxy server running on port 3001");
});
Enter fullscreen mode Exit fullscreen mode

Conclusion

Integrating open-weight LLM APIs is refreshingly similar to working with any REST API — no exotic tooling required. The key advantages are cost efficiency, data privacy, and the freedom to self-host or swap models as your needs evolve.

Start small with the open-weight-3b model, add streaming for a polished UX, and scale up to larger models only when your use case demands it. Keep your API keys secure, handle errors gracefully, and you'll have a solid AI integration in production in no time.

The open-weight ecosystem is growing fast. Now's a great time to get familiar with these APIs and build the next generation of AI-powered applications.


Ready to start building? Sign up and get your API key at NovaStack.

ai #api #opensource #tutorial

Top comments (0)