AI
AI primitives, batteries included
Embeddings, vector search and RAG — built on pgvector and the Lovable AI Gateway.
gemini-2.5-pro
gemini-2.5-flash
claude-sonnet-4.5
text-embedding-3-large
Generate embeddings
typescript
const { data } = await nb.ai.embeddings.create({
model: "text-embedding-3-large",
input: ["Hello world", "indxBASE is awesome"],
});
// data.embeddings : number[][]Store vectors in Postgres
sql
create extension if not exists vector;
create table public.documents (
id uuid primary key default gen_random_uuid(),
content text not null,
embedding vector(1536)
);
create index on public.documents using hnsw (embedding vector_cosine_ops);Vector search
typescript
const { data: hits } = await nb.rpc("match_documents", {
query_embedding: queryVec,
match_count: 5,
threshold: 0.78,
});sql
create or replace function public.match_documents(
query_embedding vector(1536),
match_count int,
threshold float
) returns table (id uuid, content text, similarity float)
language sql stable as $$
select id, content, 1 - (embedding <=> query_embedding) as similarity
from public.documents
where 1 - (embedding <=> query_embedding) > threshold
order by embedding <=> query_embedding
limit match_count;
$$;RAG: ask your data
typescript
const question = "What changed in v2.0?";
const queryVec = (await nb.ai.embeddings.create({ model: "text-embedding-3-large", input: question })).data.embeddings[0];
const { data: ctx } = await nb.rpc("match_documents", {
query_embedding: queryVec, match_count: 5, threshold: 0.75,
});
const answer = await nb.ai.chat.completions.create({
model: "google/gemini-2.5-flash",
messages: [
{ role: "system", content: "Answer using the provided context only." },
{ role: "user", content: `Context:\n${ctx.map(c => c.content).join("\n---\n")}\n\nQ: ${question}` },
],
});Streaming chat
typescript
const stream = await nb.ai.chat.completions.stream({
model: "google/gemini-2.5-pro",
messages: [{ role: "user", content: "Write a haiku about Postgres." }],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}