Bring your own models
CiteNexus bundles no models. Embedding, LLM, and optionally a reranker and a vision model for figures are injected by you. The shipped clients speak the OpenAI API — nothing runs locally that you didn’t wire up, and the key stays in your endpoint config.
The two clients every port ships
Section titled “The two clients every port ships”Embedding and chat generation are the seams all three ports consume, so all three
ship a client for them. Same endpoint, same ${ENV} header convention, one tab
per language:
from citenexus import OpenAICompatibleEmbedding, OpenAICompatibleGenerator
embedder = OpenAICompatibleEmbedding(base_url="…/v1", model="bge-m3")generator = OpenAICompatibleGenerator(base_url="…/v1", model="qwen2.5")import "github.com/muthuishere/citenexus/golang/models"
// A real net/http transport; timeout 0 means the 60s default.http := models.NewHTTPClient(nil, 0)
embedder := models.NewOpenAIEmbedding("…/v1", "bge-m3", http.Transport())generator := models.NewOpenAIChatGenerator( "…/v1", "qwen2.5", 0.0, nil, // temperature, max_tokens (nil → omitted from the request) http.Transport(),)import { HttpClient, OpenAIChatGenerator, OpenAIEmbedder } from "@muthuishere/citenexus";
const http = new HttpClient();const send = (url: string, body: string, headers: Record<string, string>) => http.send(url, body, headers);
const embedder = new OpenAIEmbedder({ base_url: "…/v1", model: "bge-m3" }, send);const generator = new OpenAIChatGenerator({ base_url: "…/v1", model: "qwen2.5" }, send);Auth on all three — ${ENV} templates expanded at the request boundary, never
stored — is in Custom endpoints & auth.
Reranker and vision, and wiring it all up
Section titled “Reranker and vision, and wiring it all up”The other two shipped clients, and the CiteNexus(...) constructor that consumes
them, are Python. All four Python clients import from the top-level package and
share one constructor shape (keyword-only base_url, model, transport,
headers, plus role-specific extras):
from citenexus import ( CiteNexus, OpenAICompatibleEmbedding, OpenAICompatibleGenerator, OpenAICompatibleReranker, OpenAICompatibleVision,)
rag = CiteNexus( "./citenexus-data", embedder=OpenAICompatibleEmbedding(base_url="…/v1", model="bge-m3"), generator=OpenAICompatibleGenerator(base_url="…/v1", model="qwen2.5"), vision=OpenAICompatibleVision(base_url="…/v1", model="qwen2.5-vl"), # figures → cited evidence)Any endpoint that speaks the OpenAI API works — Ollama, OpenAI, a local vLLM or
llama.cpp server, or Gemini’s OpenAI-compatibility endpoint. The two shipped
examples (examples/multilingual and examples/law-authority) run on hosted
Jina + Gemini, which is the cheap default stack. For an all-local run,
task local:ollama:up pulls the Ollama variant — bge-m3, qwen2.5, and the
reranker xitao/bge-reranker-v2-m3 (note the xitao/ prefix).
Wiring a model these clients can’t reach over HTTP — an in-process ONNX or
llama.cpp model, a local daemon, an SDK you already use, a test fixture — is one
line, transport=: Bring your own model — swap the
transport.
Go deeper on each: Custom endpoints & auth · Reranking & retrieval · Vision — figures as cited evidence.