Azpg pgvector rag
Skill lestermarch/postgres-ai-experts/skills/azpg-pgvector-rag
Design and implement vector / RAG search on Azure Database for PostgreSQL Flexible Server using pgvector, the azure_ai extension (in-database Azure OpenAI embeddings) and DiskANN / HNSW / IVFFlat indexing. Use this skill whenever the task involves semantic search, embeddings, RAG retrieval, similarity search, "nearest neighbour", a vector column, an embeddings pipeline, or vector index tuning on Azure Postgres — even when the user does not say the word "pgvector". Covers extension allow-listing, CREATE EXTENSION, azure_ai.set_setting, azure_openai.create_embeddings, choosing and building a vector index, and writing the retrieval query.From its SKILL.md
npx -y skills add lestermarch/postgres-ai-experts --skill azpg-pgvector-ragAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
12.0 KB, ~2.8k tokens by cl100k_base, as published. Nobody here has run it
pgvector RAG on Azure Database for PostgreSQL Flexible Server
Build vector / RAG search on Flexible Server using pgvector for storage and
similarity, the azure_ai extension for in-database Azure OpenAI embeddings,
and DiskANN / HNSW / IVFFlat for approximate nearest-neighbour indexing.
This skill is read-write. Inspection is safe and runs automatically; anything
that mutates the server or database (allow-listing extensions, CREATE EXTENSION,
CREATE INDEX, bulk embedding) is a guarded write — present a plan, get
explicit confirmation, and run the bundled scripts/ (transaction-wrapped,
--dry-run capable) rather than free-handing destructive SQL. See
Safety protocol.
All SQL and CLI in this skill is verified against Microsoft Learn (
azure_ai,pgvector,pg_diskannon Flexible Server). Do not substitute unverified syntax. For parameter-level depth beyond this file, readreference.md; for platform limits readazure-constraints.md.
Live instance context (dynamic injection)
Read the target instance's live state before recommending anything, so guidance
is version-aware rather than hardcoded. Assumes PGCONN is a libpq connection
string (or set PGHOST/PGDATABASE/PGUSER/PGPASSWORD) and the Azure CLI is logged
in. These are read-only and safe to auto-run.
- Installed vector-stack extensions and versions:
!
psql "$PGCONN" -tAc "SELECT extname, extversion FROM pg_extension WHERE extname IN ('vector','azure_ai','pg_diskann') ORDER BY extname;" 2>/dev/null || echo "(could not connect — ask the user for connection details)" - Server allow-list (what CAN be created here):
!
psql "$PGCONN" -tAc "SHOW azure.extensions;" 2>/dev/null || echo "(unknown — check azure.extensions parameter)" - Postgres major version:
!
psql "$PGCONN" -tAc "SHOW server_version;" 2>/dev/null || echo "(unknown)"
If injection is unavailable in the current runtime, run
scripts/inspect_vector_readiness.sql
and read its output instead. Never assume an extension is installed — verify.
When to use this skill
Trigger on: "semantic search over my documents", "add RAG to this app", "store
embeddings in Postgres", "find similar rows/products/tickets", "vector index is
slow", "which index — HNSW or DiskANN?", "generate embeddings in SQL", or any
schema with a vector(...) column. If the task is purely lexical full-text
search with no embeddings, prefer fulltext-and-bm25; for combining both, this
skill hands off to hybrid-search-rrf.
Decision flow
Work through these in order. Steps 1–2 are read/inspect (safe); steps 3–6 are write/mutate (guarded).
- Inspect the live instance (section above). Establish: is
vectorinstalled?azure_ai?pg_diskann? What is on the allow-list? What is the embedding source and dimension? - Design the schema and choose an index. Use the tables below plus
reference.mdto pick DiskANN vs HNSW vs IVFFlat and the distance operator. Decide dimension from the embedding model (e.g.text-embedding-3-small→ 1536;text-embedding-3-large→ 3072). - Enable extensions (guarded write) — allow-list +
CREATE EXTENSION. - Configure
azure_ai(guarded write) — endpoint + auth for Azure OpenAI. - Ingest + embed (guarded write) — populate the vector column in batches.
- Index + query — build the ANN index (guarded write), then write the retrieval query (read).
Choosing an index (summary)
| Index | Build cost | Recall/latency | Best for | Notes |
|---|---|---|---|---|
DiskANN (diskann) | Moderate, parallelisable | Excellent balance | Large / growing sets, >1M rows, high-dim | Flexible-Server-only; PQ enables >2000 dims |
HNSW (hnsw) | Higher memory/time | Best speed-recall at small–mid scale | ≤ a few M rows | ≤2000 dims for the index |
IVFFlat (ivfflat) | Cheapest | Lower recall | Fast builds, cost-sensitive | Needs data loaded before build (k-means) |
Full guidance and parameter tables: reference.md.
Distance operator ↔ ops-class (must match)
Pick one and keep the operator and index ops-class aligned, or the planner will ignore the index:
| Metric | Operator | ops-class |
|---|---|---|
| Cosine distance | <=> | vector_cosine_ops |
| Euclidean (L2) | <-> | vector_l2_ops |
| (Negative) inner product | <#> | vector_ip_ops |
For normalised embeddings (OpenAI vectors have length 1), inner product <#> is
cheapest; cosine <=> is the safe default. Use the same metric for the index
and every query.
Read / inspect steps (safe · auto)
These never mutate state. Run them freely to ground your recommendations.
-
Readiness report —
scripts/inspect_vector_readiness.sqllists the vector stack, the allow-list, existingvectorcolumns, existing ANN indexes, and whetherazure_aisettings are configured. -
Confirm an index is used —
EXPLAINa representative query and check for anIndex Scan using ...(notSeq Scan):EXPLAIN (ANALYZE, VERBOSE, BUFFERS) SELECT id FROM docs ORDER BY embedding <=> '[0.1,0.2,0.3]' LIMIT 5; -
Check index build progress (safe, during a long build):
SELECT phase, round(100.0 * blocks_done / nullif(blocks_total, 0), 1) AS "%" FROM pg_stat_progress_create_index;
Write / mutate steps (explicit · guarded)
Do not run these without presenting a plan and getting explicit confirmation.
Prefer the bundled scripts — they are transaction-wrapped where possible and
support --dry-run. On Flexible Server there is no superuser; extensions must
be on the azure.extensions allow-list first (a server parameter change that may
trigger a brief deployment). See azure-constraints.md.
3 · Enable extensions
Allow-list at the server, then create in each database. pgvector's extension
name is vector (not "pgvector"). Use
scripts/enable_extensions.sh — it does the
az ... parameter set allow-list step and the transaction-wrapped
CREATE EXTENSION step, and prints everything under --dry-run without changing
anything.
Verified underlying commands:
az postgres flexible-server parameter set \
--resource-group <rg> --server-name <server> \
--name azure.extensions --value "vector,azure_ai,pg_diskann"
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS azure_ai;
CREATE EXTENSION IF NOT EXISTS pg_diskann CASCADE; -- CASCADE pulls in vector
4 · Configure azure_ai (Azure OpenAI)
Point azure_ai at an Azure OpenAI resource with a deployed embeddings model.
Only superusers and members of azure_ai_settings_manager may call
set_setting; on Flexible Server azure_pg_admin holds this by default.
SELECT azure_ai.set_setting('azure_openai.endpoint', 'https://<name>.openai.azure.com');
-- Preferred: managed identity (no secret in the DB). See azure-constraints.md.
SELECT azure_ai.set_setting('azure_openai.auth_type', 'managed-identity');
-- Or, key-based:
-- SELECT azure_ai.set_setting('azure_openai.subscription_key', '<API key>');
Verify: SELECT azure_ai.get_setting('azure_openai.endpoint'); and
SELECT azure_ai.version();. The API-key path writes a secret into settings —
treat that as sensitive and prefer managed identity.
5 · Ingest + embed
Store embeddings in a vector(<dim>) column. azure_openai.create_embeddings
generates them in-database; the text[] overload with batch_size is far more
efficient for bulk loads than row-by-row calls. Use
scripts/bulk_embed.sh (batched, transaction-wrapped,
--dry-run reports the backfill count and cost estimate without calling the API).
-- Single value → real[]; cast to vector for storage/search.
INSERT INTO docs (body, embedding)
VALUES ('some text',
azure_openai.create_embeddings('<deployment>', 'some text')::vector);
Load data before building the ANN index — it is faster and yields a better layout (essential for IVFFlat's k-means; recommended for all types).
6 · Index + query
Build the chosen ANN index with a matching ops-class, then query with the
matching operator. Use
scripts/create_vector_index.sh
(--index-type diskann|hnsw|ivfflat, transaction-wrapped, --dry-run,
optional --concurrently for online builds that must run outside a transaction).
-- DiskANN (Flexible Server): great default for scale.
CREATE INDEX ON docs USING diskann (embedding vector_cosine_ops);
-- HNSW: strong speed-recall at ≤2000 dims.
CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- Retrieval (cosine): operator MUST match the ops-class.
SELECT id, body
FROM docs
ORDER BY embedding <=> azure_openai.create_embeddings('<deployment>', 'user query')::vector
LIMIT 5;
Recall/latency knobs (per-session or SET LOCAL in a txn):
SET hnsw.ef_search = 100;, SET diskann.l_value_is = 100;,
SET ivfflat.probes = 10;. Parameter tables and the DiskANN PQ / high-dimension
path are in reference.md.
A complete end-to-end walkthrough with expected output is in
examples/basic_rag.md. For blending vector with lexical
ranking, hand off to hybrid-search-rrf.
Safety protocol
- Inspect first. Always read live state before proposing writes; never assume an extension, setting, or index exists.
- Plan → confirm → execute for every mutating step. State exactly what will change (server parameter, which database, which table/index) and the blast radius before running.
- Use the scripts, not free-hand DDL for allow-listing,
CREATE EXTENSION, index builds, and bulk embedding. Run--dry-runfirst and show the user the planned statements. - Prefer online / low-lock paths on populated tables:
CREATE INDEX CONCURRENTLY(note: cannot run inside a transaction block) and scalemaintenance_work_memup for the build, then back down. - Precheck backups before schema-destructive changes — Flexible Server
provides automated backups/PITR; confirm the restore point is recent. See
azure-constraints.md. - Guard secrets. Prefer managed-identity auth for
azure_ai; never commit an API key or echo it into logs. - Contain blast radius. Run mutating work in a subagent where the harness supports it.
Bundled files
reference.md— deep reference: embedding models & dimensions, index deep-dive (DiskANN PQ, HNSW/IVFFlat params, recall/latency tables), distance functions, dimensionality limits, troubleshooting.azure-constraints.md— Flexible Server specifics: no superuser, allow-listing, managed identity, HA/backup, version drift.scripts/— deterministic, guarded helpers (one read-only inspector; three--dry-run-capable writers).examples/basic_rag.md— end-to-end worked example with expected output.
What ships with it: 10 files
49.5 KB alongside SKILL.md, 3 of them executable
examples/
- basic_rag.md5.1 KB
scripts/
- bulk_embed.shruns4.8 KB
- create_vector_index.shruns4.3 KB
- enable_extensions.shruns4.0 KB
- inspect_vector_readiness.sql3.8 KB
- README.md1.5 KB
- azure-constraints.md5.6 KB
- EVALUATION.md8.6 KB
- .gitattributes108 B
- reference.md11.7 KB