Switch language

RAG Pipeline

A minimal retrieval-augmented generation flow using keyword retrieval and chat completions.

This walkthrough keeps a tiny in-memory knowledge base, retrieves relevant snippets with simple keyword overlap, then answers the user with chat completions grounded in that context.

For production you would replace the in-memory store with a vector database and your own chunking pipeline. See Create chat completion and the Model Catalog.

Python implementation

import os
import re
from openai import OpenAI

client = OpenAI(
    base_url="https://api-inference.bitdeer.ai/v1",
    api_key=os.environ.get("BITDEER_API_KEY", "YOUR_API_KEY"),
)

DOCUMENTS = [
    "Bitdeer AI offers POST /v1/chat/completions for OpenAI-compatible chat.",
    "Self-deployed text models include deepseek-ai/DeepSeek-V4-Pro and Qwen/Qwen3.5-397B-A17B.",
    "Vision input uses a vision-capable model ID via image_url in messages.",
    "See the model catalog for the full list of self-deployed model IDs.",
]


def tokenize(text: str) -> set[str]:
    return {w for w in re.findall(r"[a-zA-Z0-9]+", text.lower()) if len(w) > 2}


def retrieve(query: str, top_k: int = 3) -> str:
    q = tokenize(query)
    scored = []
    for i, doc in enumerate(DOCUMENTS):
        overlap = len(q & tokenize(doc))
        if overlap:
            scored.append((overlap, i))
    scored.sort(reverse=True)
    chosen = [DOCUMENTS[i] for _, i in scored[:top_k]]
    return "\n\n".join(chosen) if chosen else DOCUMENTS[0]


def answer(query: str) -> str:
    context = retrieve(query)
    completion = client.chat.completions.create(
        model="deepseek-ai/DeepSeek-V4-Pro",
        messages=[
            {
                "role": "system",
                "content": (
                    "You are a support assistant. Answer using ONLY the context below. "
                    "If the context does not contain the answer, say you don't know.\n\n"
                    f"Context:\n{context}"
                ),
            },
            {"role": "user", "content": query},
        ],
        max_tokens=512,
    )
    return completion.choices[0].message.content or ""


if __name__ == "__main__":
    q = "Which vision model supports image input on Bitdeer AI?"
    print(answer(q))

JavaScript implementation

import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.BITDEER_API_KEY!,
  baseURL: 'https://api-inference.bitdeer.ai/v1',
});

const DOCUMENTS = [
  'Bitdeer AI offers POST /v1/chat/completions for OpenAI-compatible chat.',
  'Self-deployed text models include deepseek-ai/DeepSeek-V4-Pro and Qwen/Qwen3.5-397B-A17B.',
  'Vision input uses a vision-capable model ID via image_url in messages.',
  'See the model catalog for the full list of self-deployed model IDs.',
];

function tokenize(text: string) {
  return new Set(
    (text.toLowerCase().match(/[a-z0-9]+/g) ?? []).filter((w) => w.length > 2),
  );
}

function retrieve(query: string, topK = 3) {
  const q = tokenize(query);
  const scored = DOCUMENTS.map((doc, i) => {
    const d = tokenize(doc);
    const overlap = [...q].filter((w) => d.has(w)).length;
    return { overlap, i };
  })
    .filter((x) => x.overlap > 0)
    .sort((a, b) => b.overlap - a.overlap)
    .slice(0, topK);
  const chosen = scored.map((x) => DOCUMENTS[x.i]);
  return chosen.length ? chosen.join('\n\n') : DOCUMENTS[0];
}

export async function answer(query: string) {
  const context = retrieve(query);
  const completion = await client.chat.completions.create({
    model: 'deepseek-ai/DeepSeek-V4-Pro',
    messages: [
      {
        role: 'system',
        content:
          'You are a support assistant. Answer using ONLY the context below. ' +
          "If the context does not contain the answer, say you don't know.\n\n" +
          `Context:\n${context}`,
      },
      { role: 'user', content: query },
    ],
    max_tokens: 512,
  });
  return completion.choices[0]?.message?.content ?? '';
}

// await answer('Which vision model supports image input on Bitdeer AI?');

Key points

  • Retrieve — keyword overlap is a simple baseline; swap in your vector store when you need semantic search at scale.
  • Generate — inject retrieved text into a system message and keep the model constrained to cited facts.
  • Models — use IDs from the Model Catalog; this example uses deepseek-ai/DeepSeek-V4-Pro for answers.
  • Next steps — chunking, hybrid search, citations, and evaluation loops; LangChain patterns appear in the LangChain guide.

Last updated on

On this page

RAG Pipeline · Bitdeer AI