victorzhuk/skills

z-go-pgvector

pgvector-backed similarity search in Go — declaring vector(N) columns, encoding []float32 via pgvector.NewVector, L2/cosine/inner-product distance operators, ORDER BY / LIMIT k queries, and choosing exact scan vs ivfflat vs hnsw indexes.

Voir la source

Mode d’emploi

  1. Copiez la commande et examinez le paquet avant de l’installer dans votre environnement agent.
  2. Consultez le document original pour les outils, identifiants et environnements requis.
  3. Décrivez les entrées et le livrable souhaité ; comparez la sortie aux sources.
npx skills add https://github.com/victorzhuk/skills --skill z-go-pgvector

Avant de commencer

  • L’installation n’inclut ni abonnement au modèle, ni quota API, ni accès aux fichiers.
  • Étoiles et installations reflètent l’activité, pas un test indépendant de qualité ou de sécurité.
Document Skill original

Rendu depuis le dépôt source en conservant titres, exemples, code, tableaux, liens et images.

pgvector similarity search in Go

pgvector is a PostgreSQL extension that adds a vector type and distance operators for ANN search. github.com/pgvector/pgvector-go wraps a []float32 in a pgvector.Vector that pgx sends as a regular query parameter — no ORM, no manual text encoding, once pgxvec.RegisterTypes is wired into the pool.

Extension and column

sql
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE items (
    id      bigserial PRIMARY KEY,
    content text      NOT NULL,
    embedding vector(1536)  -- dimension must match your model's output
);

The dimension is fixed at column creation. Changing it later requires ALTER TABLE items ALTER COLUMN embedding TYPE vector(N) plus re-embedding every row.

Encoding []float32 for a query

Primary: github.com/pgvector/pgvector-go wraps a []float32 in a pgvector.Vector that pgx sends as a query parameter directly — no manual casting.

go
import (
    "github.com/jackc/pgx/v5"
    "github.com/jackc/pgx/v5/pgxpool"
    "github.com/pgvector/pgvector-go"
    pgxvec "github.com/pgvector/pgvector-go/pgx"
)

cfg, err := pgxpool.ParseConfig(dsn)
if err != nil {
    return nil, fmt.Errorf("parse pool config: %w", err)
}
cfg.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error {
    return pgxvec.RegisterTypes(ctx, conn)
}
pool, err := pgxpool.NewWithConfig(ctx, cfg)

pgxvec.RegisterTypes in AfterConnect runs once per pooled connection. After that, every SQL site passes pgvector.NewVector(vec) as a plain $n parameter:

go
_, err = pool.Exec(ctx,
    "INSERT INTO items (content, embedding) VALUES ($1, $2)",
    content, pgvector.NewVector(embedding))

Fallback: skip the dependency and encode the vector as a Postgres text literal yourself, cast with ::vector at the call site:

go
func toVectorLiteral(v []float32) string {
    parts := make([]string, len(v))
    for i, f := range v {
        parts[i] = fmt.Sprintf("%g", f)
    }
    return "[" + strings.Join(parts, ",") + "]"
}
go
_, err = pool.Exec(ctx,
    "INSERT INTO items (content, embedding) VALUES ($1, $2::vector)",
    content, toVectorLiteral(embedding))

Distance operators

OperatorDistanceNotes
<->L2 (Euclidean)default; good for normalized unit vectors
<=>cosineuse when vector magnitude is not meaningful
<#>inner productmultiply by -1 to get similarity

Choose one and be consistent — the index operator class must match the query operator (see Index trade-off below).

k-nearest-neighbour query

sql
SELECT id, content,
       embedding <=> $1 AS distance
FROM items
ORDER BY distance
LIMIT $2
go
type Result struct {
    ID       int64
    Content  string
    Distance float64
}

func Search(ctx context.Context, db *pgxpool.Pool, embedding []float32, k int) ([]Result, error) {
    rows, err := db.Query(ctx,
        `SELECT id, content, embedding <=> $1 AS distance
         FROM items
         ORDER BY distance
         LIMIT $2`,
        pgvector.NewVector(embedding), k)
    if err != nil {
        return nil, fmt.Errorf("vector search: %w", err)
    }
    defer rows.Close()

    var out []Result
    for rows.Next() {
        var r Result
        if err := rows.Scan(&r.ID, &r.Content, &r.Distance); err != nil {
            return nil, fmt.Errorf("scan: %w", err)
        }
        out = append(out, r)
    }
    return out, rows.Err()
}

Apply a distance threshold in SQL or after retrieval according to the contract. Either can yield zero matches. Post-filtering a limited candidate set can yield fewer than k results:

go
const maxDistance = 0.35

var filtered []Result
for _, r := range results {
    if r.Distance <= maxDistance {
        filtered = append(filtered, r)
    }
}

Embedder interface

Define the embedder on the consumer side (use-case or repository package), not in the infra package:

go
type Embedder interface {
    Embed(ctx context.Context, text string) ([]float32, error)
}

Validate dimensionality at the infra boundary before returning:

go
if len(vec) != cfg.Dim {
    return nil, fmt.Errorf("embed: got %d dims, want %d", len(vec), cfg.Dim)
}

Wire any OpenAI-compatible provider (OpenAI, Azure, LM Studio, vLLM) behind this interface. Do not mark the API key as required if local keyless providers must be supported.

Index trade-off

Exact scanivfflathnsw
IndexnoneCREATE INDEX … USING ivfflatCREATE INDEX … USING hnsw
Build time—fastslow (memory-intensive)
Query speedO(n) full scanfastfaster
Recallexactmeasure against exact search; tune lists/probesmeasure against exact search; tune ef_search and index construction
When to addmeets measured latencyrepresentative recall/latency justifies the indexrepresentative recall/latency/memory justifies the index

Start without an index. Exact scan is accurate and simple; add an index only after profiling shows it matters.

sql
-- ivfflat: lists ≈ sqrt(row_count), probe at query time with SET ivfflat.probes
CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

-- hnsw: higher m = better recall, more memory
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);

The operator class (vector_cosine_ops, vector_l2_ops, vector_ip_ops) must match the distance operator used in queries.

Do not

  • Skip pgxvec.RegisterTypes in AfterConnect when using pgvector-go — without

it pgx has no codec for pgvector.Vector and the query fails to encode.

  • Forget the ::vector cast on the hand-rolled text-literal fallback — Postgres

can't infer the column type from a bare string parameter.

  • Change the vector column dimension without re-embedding all rows and running

a migration.

  • Assume a WHERE distance predicate categorically disables ANN indexing. Preserve an indexable distance ORDER BY and LIMIT; inspect EXPLAIN. For filtered ANN search, evaluate iterative scans and the documented materialized-CTE pattern for distance filters. See pgvector filtering.
  • Mix operator classes between the index and query — results will be wrong

or the index unused.

Verify

sh
# extension present
psql -c "SELECT extversion FROM pg_extension WHERE extname = 'vector';"

# column type and dimension
psql -c "\d+ items"

# inspect the actual query with a nonzero vector matching the column dimension
# compare ANN recall against exact search on representative data

timeout 5m go test -parallel 4 -p 2 -short -race -timeout 5m ./internal/repository/...
du même dépôt

Autres Skills

Tous les Skills
victorzhuk
Communauté

z-accessibility

Audit and improve web accessibility following WCAG 2.2 guidelines. Use when asked to "improve accessibility", "a11y audit", "WCAG compliance", "screen reader support", "keyboard navigation", or "make accessible".

installations
1
GitHub Stars
0
Mis à jour
22 oct.
victorzhuk
Communauté

z-algo-core

DS/algorithm selection judgment for production code, not competitive tricks — hash map for membership/dedup, slice+sort beats a tree until proven, heap for top-k, two-pointer/sliding-window for scans, BFS/DFS/topo-sort for dependency shapes. Triggers on Big-O, hash map vs tree. Does not cover profiling/tuning; see [[z-go-performance]].

installations
1
GitHub Stars
0
Mis à jour
22 oct.
victorzhuk
Communauté

z-bdd

BDD acceptance contracts for humans and agents across UI, API, and CLI products. Use for Gherkin, Given-When-Then, E2E acceptance, or scenario evidence. Define repeatable scenarios with explicit assertions and required outcomes. Test selection belongs to [[z-testing-strategy]]. Go harness wiring belongs to [[z-go-bdd]].

installations
1
GitHub Stars
0
Mis à jour
22 oct.
victorzhuk
Communauté

z-codegraph

Use an existing CodeGraph integration for call graphs, impact analysis, affected tests, or route discovery. Discover installed tools and index freshness; follow host LSP precedence and verify current source. Do not initialize indexes without user authorization.

installations
1
GitHub Stars
0
Mis à jour
22 oct.