# pgvector

pgvector adds a vector column and a nearest-neighbor search to Postgres. The database does not call the exchange. Your code gets the vectors from the exchange and stores them in the table.

## Before you start

- A workspace with a balance and a `spend` key. See [API keys](https://inference.ai.exchange/docs/keys.md).
- A Postgres database where you can run `CREATE EXTENSION vector`.
- A model name from `GET /v1/models?kind=embedding`. See [Embeddings](https://inference.ai.exchange/docs/embeddings.md).

## 1. Export the key

```bash
export LIQUID_API_KEY=sk-liquid-...
export DATABASE_URL=postgresql://user:password@host:5432/dbname
```

## 2. Install the packages

```bash
# Python 3.9 or later
pip install openai "psycopg[binary]"
```

## 3. Create the table and store vectors

The column length must equal the vector length of the model. `text-embedding-3-small` returns 1,536 numbers. A model with a different length needs a different column.

**SQL**

```sql
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
  id bigserial PRIMARY KEY,
  body text NOT NULL,
  embedding vector(1536) NOT NULL
);

CREATE INDEX documents_embedding_idx
  ON documents USING hnsw (embedding vector_cosine_ops);
```

**Python**

```python
import os

import psycopg
from openai import OpenAI

MODEL = "text-embedding-3-small"
client = OpenAI(
    base_url="https://router.inference.ai.exchange/v1",
    api_key=os.environ["LIQUID_API_KEY"],
)

def embed(texts):
    result = client.embeddings.create(model=MODEL, input=texts)
    return [item.embedding for item in result.data]

texts = ["a cat on a bicycle", "a dog in a car"]
with psycopg.connect(os.environ["DATABASE_URL"]) as conn:
    for text, vector in zip(texts, embed(texts)):
        conn.execute(
            "INSERT INTO documents (body, embedding) VALUES (%s, %s::vector)",
            (text, str(vector)),
        )

    query = embed(["an animal on two wheels"])[0]
    rows = conn.execute(
        "SELECT body, embedding <=> %s::vector AS distance "
        "FROM documents ORDER BY distance LIMIT 3",
        (str(query),),
    ).fetchall()
    for body, distance in rows:
        print(f"{distance:.3f}  {body}")
```

The operator `<=>` is the cosine distance, so the index uses `vector_cosine_ops`. Use the same model for the stored texts and for the query.

## Notes

- Send the texts in batches of up to 2,048. One request is one auction and has one cap.
- Keep one model for one table. A change of model needs a new column and a new embed of every row. See [Embeddings](https://inference.ai.exchange/docs/embeddings.md).
- An index of type `hnsw` supports vectors of up to 2,000 numbers. For a longer vector, use the `halfvec` type or set `dimensions` to a shorter length on a model that supports it.
- The exchange sets a cap on each request. It is in the `x-liquid-cap-usd` response header. To limit total spend, set a spending limit on the key. See [API keys](https://inference.ai.exchange/docs/keys.md).

## Troubleshooting

| Symptom                                 | Cause and fix                                                                        |
| --------------------------------------- | ------------------------------------------------------------------------------------ |
| `expected 1536 dimensions, not 1024`    | The column length differs from the model. Create the column with the model's length. |
| `401`                                   | The key is wrong, revoked or expired. Export it again.                               |
| `model_not_found`                       | The model is not on the book. Use an exact name from `GET /v1/models`.               |
| A request is refused for lack of funds. | The workspace balance cannot cover the cap. Add funds on the **Credits** page.       |

See [Errors](https://inference.ai.exchange/docs/errors.md) for the error codes.

## Next steps

- [Embeddings](https://inference.ai.exchange/docs/embeddings.md): the request, the price and the limits.
- [Qdrant](https://inference.ai.exchange/docs/connect-qdrant.md) and [Pinecone](https://inference.ai.exchange/docs/connect-pinecone.md): a database that is only for vectors.
