# Pinecone

Pinecone is a hosted vector database. It does not call the exchange. Your code gets the vectors from the exchange and writes them to a Pinecone index.

## Before you start

- A workspace with a balance and a `spend` key. See [API keys](https://inference.ai.exchange/docs/keys.md).
- A Pinecone account and API key.
- A model name from `GET /v1/models?kind=embedding`. See [Embeddings](https://inference.ai.exchange/docs/embeddings.md).

## 1. Export the keys

```bash
export LIQUID_API_KEY=sk-liquid-...
export PINECONE_API_KEY=...
```

## 2. Install the packages

```bash
# Python 3.9 or later
pip install openai pinecone
```

## 3. Store and search

Create the index with the vector length of the model. `text-embedding-3-small` returns 1,536 numbers. Do not use a Pinecone integrated model: that index embeds the text itself and does not take your vectors.

```python
import os

from openai import OpenAI
from pinecone import Pinecone, ServerlessSpec

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

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

if not pc.has_index("documents"):
    pc.create_index(
        name="documents",
        dimension=1536,
        metric="cosine",
        spec=ServerlessSpec(cloud="aws", region="us-east-1"),
    )
index = pc.Index("documents")

texts = ["a cat on a bicycle", "a dog in a car"]
index.upsert(
    vectors=[
        {"id": f"doc-{i}", "values": vector, "metadata": {"body": text}}
        for i, (text, vector) in enumerate(zip(texts, embed(texts)))
    ]
)

result = index.query(
    vector=embed(["an animal on two wheels"])[0],
    top_k=3,
    include_metadata=True,
)
for match in result.matches:
    print(f"{match.score:.3f}  {match.metadata['body']}")
```

A new write can take a few seconds to appear in a query. Use the same model for the stored texts and for the query.

## Notes

- Send the texts in batches of up to 2,048 to the exchange. Pinecone limits the size of an upsert request, so write the vectors in smaller batches, for example 100 at a time.
- Keep one model for one index. A change of model needs a new index and a new embed of every record. See [Embeddings](https://inference.ai.exchange/docs/embeddings.md).
- 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                                                                             |
| --------------------------------------- | ----------------------------------------------------------------------------------------- |
| `Vector dimension 1024 does not match`  | The index length differs from the model. Create the index with the model's vector length. |
| `401` from the exchange                 | 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 [pgvector](https://inference.ai.exchange/docs/connect-pgvector.md): other places to keep the vectors.
