From 7f374e39091a16eed6763c09ce169a63a241b63b Mon Sep 17 00:00:00 2001 From: Alejandro Do Nascimento Mora Date: Tue, 17 Mar 2026 11:38:21 +0100 Subject: [PATCH 1/4] Add vectorizer and in-database llm call deprecation --- ai/page-index/page-index.js | 5 + ai/vectorizer-deprecation.md | 362 +++++++++++++++++++++++++++++++++++ 2 files changed, 367 insertions(+) create mode 100644 ai/vectorizer-deprecation.md diff --git a/ai/page-index/page-index.js b/ai/page-index/page-index.js index b3735bbc4d..4e3a5d354e 100644 --- a/ai/page-index/page-index.js +++ b/ai/page-index/page-index.js @@ -7,6 +7,11 @@ module.exports = [ excerpt: "Integrate AI with your Tiger Data products", children: [ + { + title: "Vectorizer and in-database LLM calls deprecation", + href: "vectorizer-deprecation", + excerpt: "Migration guide for the deprecation of managed vectorizer and in-database LLM calls on Timescale Cloud", + }, { title: "Integrate Tiger Cloud with your AI Assistant", href: "mcp-server", diff --git a/ai/vectorizer-deprecation.md b/ai/vectorizer-deprecation.md new file mode 100644 index 0000000000..bc3fad7047 --- /dev/null +++ b/ai/vectorizer-deprecation.md @@ -0,0 +1,362 @@ +--- +title: Vectorizer and in-database LLM calls deprecation +excerpt: Migration guide for the deprecation of managed vectorizer and in-database LLM calls on Timescale Cloud +products: [cloud] +keywords: [vectorizer, llm] +tags: [vectorizer, llm] +--- + +# Vectorizer and in-database LLM calls deprecation notice + +We are deprecating the following AI capabilities from $CLOUD_LONG: + +1. **Managed Vectorizer** — The cloud-managed service that automatically runs vectorizer workers will be removed. Your vectorizer definitions and embedding tables remain intact, but you will need to run the vectorizer worker yourself. + +2. **In-database LLM Calls** — Functions for calling LLM APIs from within the database (`ai.openai_embed`, `ai.openai_chat_complete`, `ai.anthropic_generate`, `ai.ollama_embed`, `ai.cohere_embed`, etc.) will be removed from Cloud. These functions will no longer be available in SQL queries. + +**Effective date: June 30, 2026.** + +Your **data is not affected**. All tables, embeddings, and vectorizer configurations remain in your database. Only the cloud-managed execution and the in-database LLM calls are being removed. + +**What is NOT changing:** Semantic search powered by [pgvector][pgvector] and [pgvectorscale][pgvectorscale], and keyword search with BM25 powered by [pg_textsearch][pg_textsearch] — the building blocks for hybrid search — remain fully available on $CLOUD_LONG. We continue to actively invest in these extensions. + +--- + +## Part 1: Migrating the vectorizer + +Your vectorizer definitions and embedding tables stay in your database. The only change is that you now run the worker yourself instead of relying on the cloud-managed scheduler. + +### Important: customers running pgai extension versions before 0.10.0 + +In extension version **0.10.0**, the vectorizer code was moved out of the pgai extension and into the standalone `pgai` Python library. If you are running a pgai extension version **older than 0.10.0** (versions 0.4.0 through 0.9.x), the vectorizer SQL objects (tables, functions) are still owned by the extension. You must upgrade before following the steps below. + +To check your current pgai extension version, run: + +```sql +SELECT extversion FROM pg_extension WHERE extname = 'ai'; +``` + +If the result is `0.9.x` or earlier, follow the upgrade steps below. If it is `0.10.0` or later, skip ahead to [Step 1: Disable the cloud scheduling](#step-1-disable-the-cloud-scheduling). + +1. **Upgrade the pgai extension** to the latest version: + + ```sql + ALTER EXTENSION ai UPDATE; + ``` + + This runs a migration that detaches the vectorizer objects from the extension without dropping them. Your vectorizer definitions and data remain intact. + +2. **Install the pgai library** to manage the vectorizer SQL objects going forward: + + Via pip: + + ```bash + pip install "pgai[vectorizer-worker]" + pgai install -d "postgres://tsdbadmin:@:/tsdb?sslmode=require" + ``` + + Or via Docker: + + ```bash + docker run --pull always --rm --entrypoint python \ + timescale/pgai-vectorizer-worker:latest \ + -m pgai install -d "postgres://tsdbadmin:@:/tsdb?sslmode=require" + ``` + +After completing these steps, proceed with the migration steps below. + +### Step 1: Disable the cloud scheduling + +Connect to your database and remove the cloud scheduler from all your vectorizers. This deletes the TimescaleDB background jobs and switches the scheduling config to `none`, while keeping the vectorizers enabled so the self-hosted worker can pick them up: + +```sql +-- Delete the TimescaleDB scheduled jobs +SELECT public.delete_job((config->'scheduling'->>'job_id')::int) +FROM ai.vectorizer +WHERE config->'scheduling'->>'implementation' = 'timescaledb'; + +-- Switch scheduling to none +UPDATE ai.vectorizer +SET config = jsonb_set(config, '{scheduling}', '{"config_type": "scheduling", "implementation": "none"}'::jsonb) +WHERE config->'scheduling'->>'implementation' = 'timescaledb'; +``` + +### Step 2: Get your connection string + +Get your $CLOUD_LONG connection string from the Cloud console. It looks like: + +``` +postgres://tsdbadmin:@:/tsdb?sslmode=require +``` + +### Step 3: Run the vectorizer worker + +Choose one of the following methods to run the worker yourself. + +#### Option A: Docker (recommended) + +Create a `.env` file with your API keys: + +``` +OPENAI_API_KEY=sk-your-openai-api-key +``` + +Run the worker: + +```bash +docker run \ + --env-file .env \ + timescale/pgai-vectorizer-worker:latest \ + --db-url "postgres://tsdbadmin:@:/tsdb?sslmode=require" \ + --poll-interval 5m \ + -c 4 +``` + +#### Option B: Docker Compose + +```yaml +name: pgai-vectorizer +services: + vectorizer-worker: + image: timescale/pgai-vectorizer-worker:latest + environment: + PGAI_VECTORIZER_WORKER_DB_URL: "postgres://tsdbadmin:@:/tsdb?sslmode=require" + OPENAI_API_KEY: "sk-your-openai-api-key" + command: ["--poll-interval", "5m", "-c", "4"] + restart: unless-stopped +``` + +Start it: + +```bash +docker compose up -d +``` + +#### Option C: CLI + +Install the pgai package: + +```bash +pip install pgai[vectorizer-worker] +``` + +Run the worker: + +```bash +export OPENAI_API_KEY=sk-your-openai-api-key +pgai vectorizer worker -d "postgres://tsdbadmin:@:/tsdb?sslmode=require" --poll-interval 5m -c 4 +``` + +#### Option D: Python integration + +```python +import asyncio +from pgai import Worker + +worker = Worker( + db_url="postgres://tsdbadmin:@:/tsdb?sslmode=require", + poll_interval=timedelta(minutes=5), + concurrency=4, +) +asyncio.run(worker.run()) +``` + +For the full worker configuration reference, see the [pgai vectorizer worker documentation][pgai-worker-docs]. + +--- + +## Part 2: Migrating away from in-database LLM calls + +The in-database LLM calls (`ai.openai_embed`, `ai.openai_chat_complete`, `ai.anthropic_generate`, etc.) are being removed. You need to move these calls to application code. + +### Migrating embedding calls + +**Before** — embedding generated inside the database: + +```sql +SELECT id, content +FROM documents +ORDER BY embedding <=> ai.openai_embed('text-embedding-3-small', 'search query') +LIMIT 5; +``` + +**After** — generate the embedding in Python, pass it to the query: + +```python +import openai +import psycopg2 + +client = openai.OpenAI() # uses OPENAI_API_KEY env var + +def semantic_search(query: str, limit: int = 5): + # Generate the embedding in your application + response = client.embeddings.create( + model="text-embedding-3-small", + input=query, + ) + embedding = response.data[0].embedding + + # Pass the embedding as a parameter to the query + conn = psycopg2.connect("postgres://tsdbadmin:@:/tsdb?sslmode=require") + cur = conn.cursor() + cur.execute( + """ + SELECT id, content + FROM documents + ORDER BY embedding <=> %s::vector + LIMIT %s + """, + (embedding, limit), + ) + return cur.fetchall() +``` + +Or with `asyncpg`: + +```python +import openai +import asyncpg + +client = openai.OpenAI() + +async def semantic_search(query: str, limit: int = 5): + response = client.embeddings.create( + model="text-embedding-3-small", + input=query, + ) + embedding = response.data[0].embedding + + conn = await asyncpg.connect("postgres://tsdbadmin:@:/tsdb?sslmode=require") + rows = await conn.fetch( + """ + SELECT id, content + FROM documents + ORDER BY embedding <=> $1::vector + LIMIT $2 + """, + str(embedding), + limit, + ) + return rows +``` + +### Migrating chat completion calls + +**Before** — chat completion inside the database: + +```sql +SELECT ai.openai_chat_complete( + 'gpt-4o', + jsonb_build_array( + jsonb_build_object('role', 'user', 'content', 'Summarize this: ' || doc.content) + ) +)->'choices'->0->'message'->>'content' AS summary +FROM documents doc +WHERE doc.id = 1; +``` + +**After** — call the API from your application: + +```python +import openai + +client = openai.OpenAI() + +def summarize(content: str) -> str: + response = client.chat.completions.create( + model="gpt-4o", + messages=[{"role": "user", "content": f"Summarize this: {content}"}], + ) + return response.choices[0].message.content +``` + +### Migrating Anthropic calls + +**Before:** + +```sql +SELECT ai.anthropic_generate( + 'claude-sonnet-4-20250514', + jsonb_build_array( + jsonb_build_object('role', 'user', 'content', 'Explain this concept') + ) +); +``` + +**After:** + +```python +import anthropic + +client = anthropic.Anthropic() + +def generate(prompt: str) -> str: + message = client.messages.create( + model="claude-sonnet-4-20250514", + max_tokens=1024, + messages=[{"role": "user", "content": prompt}], + ) + return message.content[0].text +``` + +### Migrating Cohere reranking + +**Before:** + +```sql +SELECT ai.cohere_rerank( + 'rerank-english-v3.0', + 'search query', + jsonb_agg(content) +) +FROM documents +LIMIT 100; +``` + +**After:** + +```python +import cohere + +client = cohere.Client() + +def rerank(query: str, documents: list[str]) -> list: + response = client.rerank( + model="rerank-english-v3.0", + query=query, + documents=documents, + ) + return response.results +``` + +### Summary of function replacements + +| Deprecated function | Replacement | +| ----------------------------------------------- | ------------------------------------------------------------------------- | +| `ai.openai_embed(model, text)` | `openai.OpenAI().embeddings.create(model=model, input=text)` | +| `ai.openai_chat_complete(model, messages)` | `openai.OpenAI().chat.completions.create(model=model, messages=messages)` | +| `ai.openai_chat_complete_simple(model, prompt)` | `openai.OpenAI().chat.completions.create(model=model, messages=[...])` | +| `ai.openai_moderate(model, input)` | `openai.OpenAI().moderations.create(model=model, input=input)` | +| `ai.anthropic_generate(model, messages)` | `anthropic.Anthropic().messages.create(model=model, messages=messages)` | +| `ai.ollama_embed(model, text)` | `ollama.embed(model=model, input=text)` | +| `ai.ollama_generate(model, prompt)` | `ollama.generate(model=model, prompt=prompt)` | +| `ai.ollama_chat_complete(model, messages)` | `ollama.chat(model=model, messages=messages)` | +| `ai.cohere_embed(model, text)` | `cohere.Client().embed(model=model, texts=[text])` | +| `ai.cohere_rerank(model, query, docs)` | `cohere.Client().rerank(model=model, query=query, documents=docs)` | +| `ai.cohere_chat_complete(model, messages)` | `cohere.Client().chat(model=model, messages=messages)` | +| `ai.voyageai_embed(model, text)` | `voyageai.Client().embed(texts=[text], model=model)` | +| `ai.voyageai_rerank(model, query, docs)` | `voyageai.Client().rerank(query=query, documents=docs, model=model)` | + +### General migration pattern + +For any `ai.*` function call: + +1. **Identify the provider** — the function prefix tells you (`openai_`, `anthropic_`, `ollama_`, `cohere_`, `voyageai_`) +2. **Install the provider's Python SDK** — `pip install openai`, `pip install anthropic`, etc. +3. **Move the call to your application** — call the SDK from your app code before or after your database queries +4. **Pass results as query parameters** — for embeddings, generate the vector in your app and pass it as a parameter to your SQL query + +[pgvector]: https://github.com/pgvector/pgvector +[pgvectorscale]: https://github.com/timescale/pgvectorscale +[pg_textsearch]: https://github.com/timescale/pg_textsearch +[pgai-worker-docs]: https://github.com/timescale/pgai/blob/main/docs/vectorizer/worker.md From 333fd69972bdca51766a82e5ca46c754ce5212ee Mon Sep 17 00:00:00 2001 From: atovpeko Date: Mon, 23 Mar 2026 13:58:13 +0800 Subject: [PATCH 2/4] review --- _partials/_livesync-terminal.md | 8 +- ai/page-index/page-index.js | 4 +- ai/vectorizer-deprecation.md | 592 ++++++++++++++++---------------- 3 files changed, 310 insertions(+), 294 deletions(-) diff --git a/_partials/_livesync-terminal.md b/_partials/_livesync-terminal.md index 3c81f91ed1..4ddb825b13 100644 --- a/_partials/_livesync-terminal.md +++ b/_partials/_livesync-terminal.md @@ -172,14 +172,16 @@ instance to a $SERVICE_LONG: 1. **Start the $PG_CONNECTOR** - As you run the $PG_CONNECTOR continuously, best practice is to run it as a Docker daemon. + As you run the $PG_CONNECTOR continuously, best practice is to run it as a Docker daemon. ```shell - docker run -d --rm --name livesync timescale/live-sync:v0.11.2 run \ + docker run -d --rm --name livesync timescale/live-sync: run \ --publication --subscription \ --source $SOURCE --target $TARGET --table-map ``` + `version-tag`: The latest available version tag of the live-sync image. See [Docker Hub](https://hub.docker.com/r/timescale/live-sync). + `--publication`: The name of the publication as you created in the previous step. To use multiple publications, repeat the `--publication` flag. `--subscription`: The name that identifies the subscription on the target $SERVICE_LONG. @@ -331,7 +333,7 @@ EOF Use the `--drop` flag to remove the replication slots created by the $PG_CONNECTOR on the source database. ```shell - docker run -it --rm --name livesync timescale/live-sync:v0.11.2 run \ + docker run -it --rm --name livesync timescale/live-sync: run \ --publication --subscription \ --source $SOURCE --target $TARGET \ --drop diff --git a/ai/page-index/page-index.js b/ai/page-index/page-index.js index 4e3a5d354e..9c464d0273 100644 --- a/ai/page-index/page-index.js +++ b/ai/page-index/page-index.js @@ -8,9 +8,9 @@ module.exports = [ "Integrate AI with your Tiger Data products", children: [ { - title: "Vectorizer and in-database LLM calls deprecation", + title: "Vectorizer and in-database LLM calls migration guide", href: "vectorizer-deprecation", - excerpt: "Migration guide for the deprecation of managed vectorizer and in-database LLM calls on Timescale Cloud", + excerpt: "Migration guide for the deprecation of managed vectorizer and in-database LLM calls on Tiger Cloud", }, { title: "Integrate Tiger Cloud with your AI Assistant", diff --git a/ai/vectorizer-deprecation.md b/ai/vectorizer-deprecation.md index bc3fad7047..436b656c31 100644 --- a/ai/vectorizer-deprecation.md +++ b/ai/vectorizer-deprecation.md @@ -1,44 +1,40 @@ --- -title: Vectorizer and in-database LLM calls deprecation +title: Vectorizer and in-database LLM calls migration guide excerpt: Migration guide for the deprecation of managed vectorizer and in-database LLM calls on Timescale Cloud products: [cloud] keywords: [vectorizer, llm] tags: [vectorizer, llm] --- -# Vectorizer and in-database LLM calls deprecation notice +# Vectorizer and in-database LLM calls migration guide -We are deprecating the following AI capabilities from $CLOUD_LONG: +The following AI capabilities are deprecated from $CLOUD_LONG and will be removed on **June 30, 2026**: -1. **Managed Vectorizer** — The cloud-managed service that automatically runs vectorizer workers will be removed. Your vectorizer definitions and embedding tables remain intact, but you will need to run the vectorizer worker yourself. +- **Managed Vectorizer** — the Tiger Cloud-managed service that automatically runs vectorizer workers. Your vectorizer definitions and embedding tables remain intact, but you will need to run the vectorizer worker yourself. -2. **In-database LLM Calls** — Functions for calling LLM APIs from within the database (`ai.openai_embed`, `ai.openai_chat_complete`, `ai.anthropic_generate`, `ai.ollama_embed`, `ai.cohere_embed`, etc.) will be removed from Cloud. These functions will no longer be available in SQL queries. +- **In-database LLM calls** — functions for calling LLM APIs from within the database (`ai.openai_embed`, `ai.openai_chat_complete`, `ai.anthropic_generate`, `ai.ollama_embed`, `ai.cohere_embed`, and so on). These functions will no longer be available in SQL queries. -**Effective date: June 30, 2026.** +Your **data is not affected**. All tables, embeddings, and vectorizer configurations remain in your database. Only the Tiger Cloud-managed execution and the in-database LLM calls are being removed. -Your **data is not affected**. All tables, embeddings, and vectorizer configurations remain in your database. Only the cloud-managed execution and the in-database LLM calls are being removed. +**What is not changing:** Semantic search powered by [pgvector][pgvector] and [pgvectorscale][pgvectorscale], and keyword search with BM25 powered by [pg_textsearch][pg_textsearch] — the building blocks for hybrid search — remain fully available on $CLOUD_LONG. We continue to actively invest in these extensions. -**What is NOT changing:** Semantic search powered by [pgvector][pgvector] and [pgvectorscale][pgvectorscale], and keyword search with BM25 powered by [pg_textsearch][pg_textsearch] — the building blocks for hybrid search — remain fully available on $CLOUD_LONG. We continue to actively invest in these extensions. +Your vectorizer definitions and embedding tables stay in your database. The only change is that you now run the worker yourself instead of relying on the Tiger Cloud-managed scheduler. ---- - -## Part 1: Migrating the vectorizer - -Your vectorizer definitions and embedding tables stay in your database. The only change is that you now run the worker yourself instead of relying on the cloud-managed scheduler. +## Upgrade the extension -### Important: customers running pgai extension versions before 0.10.0 +In pgai **v0.10.0**, the vectorizer code was moved out of the pgai extension and into the standalone `pgai` Python library. If you are running a pgai extension version 0.4.0 through 0.9.x, the vectorizer SQL objects (tables, functions) are still owned by the extension. Upgrade before following the migration steps: -In extension version **0.10.0**, the vectorizer code was moved out of the pgai extension and into the standalone `pgai` Python library. If you are running a pgai extension version **older than 0.10.0** (versions 0.4.0 through 0.9.x), the vectorizer SQL objects (tables, functions) are still owned by the extension. You must upgrade before following the steps below. + -To check your current pgai extension version, run: +1. **Check your current pgai version** -```sql -SELECT extversion FROM pg_extension WHERE extname = 'ai'; -``` + ```sql + SELECT extversion FROM pg_extension WHERE extname = 'ai'; + ``` + + If the result is `0.9.x` or earlier, follow the upgrade steps below. If it is `0.10.0` or later, skip to [Migrate the vectorizer][migrate-the-vectorizer]. -If the result is `0.9.x` or earlier, follow the upgrade steps below. If it is `0.10.0` or later, skip ahead to [Step 1: Disable the cloud scheduling](#step-1-disable-the-cloud-scheduling). - -1. **Upgrade the pgai extension** to the latest version: +1. **Upgrade pgai to the latest version** ```sql ALTER EXTENSION ai UPDATE; @@ -46,7 +42,7 @@ If the result is `0.9.x` or earlier, follow the upgrade steps below. If it is `0 This runs a migration that detaches the vectorizer objects from the extension without dropping them. Your vectorizer definitions and data remain intact. -2. **Install the pgai library** to manage the vectorizer SQL objects going forward: +1. **Install the pgai library to manage the vectorizer SQL objects going forward** Via pip: @@ -63,271 +59,283 @@ If the result is `0.9.x` or earlier, follow the upgrade steps below. If it is `0 -m pgai install -d "postgres://tsdbadmin:@:/tsdb?sslmode=require" ``` -After completing these steps, proceed with the migration steps below. - -### Step 1: Disable the cloud scheduling - -Connect to your database and remove the cloud scheduler from all your vectorizers. This deletes the TimescaleDB background jobs and switches the scheduling config to `none`, while keeping the vectorizers enabled so the self-hosted worker can pick them up: - -```sql --- Delete the TimescaleDB scheduled jobs -SELECT public.delete_job((config->'scheduling'->>'job_id')::int) -FROM ai.vectorizer -WHERE config->'scheduling'->>'implementation' = 'timescaledb'; - --- Switch scheduling to none -UPDATE ai.vectorizer -SET config = jsonb_set(config, '{scheduling}', '{"config_type": "scheduling", "implementation": "none"}'::jsonb) -WHERE config->'scheduling'->>'implementation' = 'timescaledb'; -``` - -### Step 2: Get your connection string - -Get your $CLOUD_LONG connection string from the Cloud console. It looks like: - -``` -postgres://tsdbadmin:@:/tsdb?sslmode=require -``` - -### Step 3: Run the vectorizer worker - -Choose one of the following methods to run the worker yourself. - -#### Option A: Docker (recommended) - -Create a `.env` file with your API keys: - -``` -OPENAI_API_KEY=sk-your-openai-api-key -``` - -Run the worker: - -```bash -docker run \ - --env-file .env \ - timescale/pgai-vectorizer-worker:latest \ - --db-url "postgres://tsdbadmin:@:/tsdb?sslmode=require" \ - --poll-interval 5m \ - -c 4 -``` - -#### Option B: Docker Compose - -```yaml -name: pgai-vectorizer -services: - vectorizer-worker: - image: timescale/pgai-vectorizer-worker:latest - environment: - PGAI_VECTORIZER_WORKER_DB_URL: "postgres://tsdbadmin:@:/tsdb?sslmode=require" - OPENAI_API_KEY: "sk-your-openai-api-key" - command: ["--poll-interval", "5m", "-c", "4"] - restart: unless-stopped -``` - -Start it: - -```bash -docker compose up -d -``` - -#### Option C: CLI - -Install the pgai package: - -```bash -pip install pgai[vectorizer-worker] -``` - -Run the worker: - -```bash -export OPENAI_API_KEY=sk-your-openai-api-key -pgai vectorizer worker -d "postgres://tsdbadmin:@:/tsdb?sslmode=require" --poll-interval 5m -c 4 -``` - -#### Option D: Python integration - -```python -import asyncio -from pgai import Worker - -worker = Worker( - db_url="postgres://tsdbadmin:@:/tsdb?sslmode=require", - poll_interval=timedelta(minutes=5), - concurrency=4, -) -asyncio.run(worker.run()) -``` - -For the full worker configuration reference, see the [pgai vectorizer worker documentation][pgai-worker-docs]. - ---- - -## Part 2: Migrating away from in-database LLM calls - -The in-database LLM calls (`ai.openai_embed`, `ai.openai_chat_complete`, `ai.anthropic_generate`, etc.) are being removed. You need to move these calls to application code. - -### Migrating embedding calls - -**Before** — embedding generated inside the database: + -```sql -SELECT id, content -FROM documents -ORDER BY embedding <=> ai.openai_embed('text-embedding-3-small', 'search query') -LIMIT 5; -``` - -**After** — generate the embedding in Python, pass it to the query: - -```python -import openai -import psycopg2 - -client = openai.OpenAI() # uses OPENAI_API_KEY env var - -def semantic_search(query: str, limit: int = 5): - # Generate the embedding in your application - response = client.embeddings.create( - model="text-embedding-3-small", - input=query, - ) - embedding = response.data[0].embedding - - # Pass the embedding as a parameter to the query - conn = psycopg2.connect("postgres://tsdbadmin:@:/tsdb?sslmode=require") - cur = conn.cursor() - cur.execute( - """ - SELECT id, content - FROM documents - ORDER BY embedding <=> %s::vector - LIMIT %s - """, - (embedding, limit), - ) - return cur.fetchall() -``` - -Or with `asyncpg`: - -```python -import openai -import asyncpg - -client = openai.OpenAI() - -async def semantic_search(query: str, limit: int = 5): - response = client.embeddings.create( - model="text-embedding-3-small", - input=query, - ) - embedding = response.data[0].embedding - - conn = await asyncpg.connect("postgres://tsdbadmin:@:/tsdb?sslmode=require") - rows = await conn.fetch( - """ - SELECT id, content - FROM documents - ORDER BY embedding <=> $1::vector - LIMIT $2 - """, - str(embedding), - limit, - ) - return rows -``` - -### Migrating chat completion calls - -**Before** — chat completion inside the database: - -```sql -SELECT ai.openai_chat_complete( - 'gpt-4o', - jsonb_build_array( - jsonb_build_object('role', 'user', 'content', 'Summarize this: ' || doc.content) - ) -)->'choices'->0->'message'->>'content' AS summary -FROM documents doc -WHERE doc.id = 1; -``` - -**After** — call the API from your application: - -```python -import openai - -client = openai.OpenAI() - -def summarize(content: str) -> str: - response = client.chat.completions.create( - model="gpt-4o", - messages=[{"role": "user", "content": f"Summarize this: {content}"}], - ) - return response.choices[0].message.content -``` - -### Migrating Anthropic calls - -**Before:** - -```sql -SELECT ai.anthropic_generate( - 'claude-sonnet-4-20250514', - jsonb_build_array( - jsonb_build_object('role', 'user', 'content', 'Explain this concept') - ) -); -``` - -**After:** - -```python -import anthropic - -client = anthropic.Anthropic() - -def generate(prompt: str) -> str: - message = client.messages.create( - model="claude-sonnet-4-20250514", - max_tokens=1024, - messages=[{"role": "user", "content": prompt}], - ) - return message.content[0].text -``` - -### Migrating Cohere reranking - -**Before:** - -```sql -SELECT ai.cohere_rerank( - 'rerank-english-v3.0', - 'search query', - jsonb_agg(content) -) -FROM documents -LIMIT 100; -``` - -**After:** - -```python -import cohere - -client = cohere.Client() +After completing these steps, proceed with the migration steps below. -def rerank(query: str, documents: list[str]) -> list: - response = client.rerank( - model="rerank-english-v3.0", - query=query, - documents=documents, +## Migrate the vectorizer + +Take the following steps to migrate the vectorizer: + + + +1. **Disable the cloud scheduling** + + Connect to your database and remove the cloud scheduler from all your vectorizers. This deletes the TimescaleDB background jobs and switches the scheduling config to `none`, while keeping the vectorizers enabled so the self-hosted worker can pick them up: + + ```sql + -- Delete the TimescaleDB scheduled jobs + SELECT public.delete_job((config->'scheduling'->>'job_id')::int) + FROM ai.vectorizer + WHERE config->'scheduling'->>'implementation' = 'timescaledb'; + + -- Switch scheduling to none + UPDATE ai.vectorizer + SET config = jsonb_set(config, '{scheduling}', '{"config_type": "scheduling", "implementation": "none"}'::jsonb) + WHERE config->'scheduling'->>'implementation' = 'timescaledb'; + ``` + +1. **Get your connection string** + + Get your [$CLOUD_LONG connection string][connection-string] from the Tiger Console. It has the following format: + + ``` + postgres://tsdbadmin:@:/tsdb?sslmode=require + ``` + +1. **Run the vectorizer worker** + + Choose one of the following methods to run the worker yourself: + + - Option A: Docker (recommended) + + Create a `.env` file with your API keys: + + ``` + OPENAI_API_KEY=sk-your-openai-api-key + ``` + + Run the worker: + + ```bash + docker run \ + --env-file .env \ + timescale/pgai-vectorizer-worker:latest \ + --db-url "postgres://tsdbadmin:@:/tsdb?sslmode=require" \ + --poll-interval 5m \ + -c 4 + ``` + + - Option B: Docker Compose + + ```yaml + name: pgai-vectorizer + services: + vectorizer-worker: + image: timescale/pgai-vectorizer-worker:latest + environment: + PGAI_VECTORIZER_WORKER_DB_URL: "postgres://tsdbadmin:@:/tsdb?sslmode=require" + OPENAI_API_KEY: "sk-your-openai-api-key" + command: ["--poll-interval", "5m", "-c", "4"] + restart: unless-stopped + ``` + + Start it: + + ```bash + docker compose up -d + ``` + + - Option C: CLI + + Install the pgai package: + + ```bash + pip install pgai[vectorizer-worker] + ``` + + Run the worker: + + ```bash + export OPENAI_API_KEY=sk-your-openai-api-key + pgai vectorizer worker -d "postgres://tsdbadmin:@:/tsdb?sslmode=require" --poll-interval 5m -c 4 + ``` + + - Option D: Python integration + + ```python + import asyncio + from pgai import Worker + + worker = Worker( + db_url="postgres://tsdbadmin:@:/tsdb?sslmode=require", + poll_interval=timedelta(minutes=5), + concurrency=4, + ) + asyncio.run(worker.run()) + ``` + + For the full worker configuration reference, see the [pgai vectorizer worker documentation][pgai-worker-docs]. + + + +## Migrate away from in-database LLM calls + +The in-database LLM calls (`ai.openai_embed`, `ai.openai_chat_complete`, `ai.anthropic_generate`, and so on) are being removed. You need to move these calls to the application code. + + + +- Migrate embedding calls + + **Before** — embedding generated inside the database: + + ```sql + SELECT id, content + FROM documents + ORDER BY embedding <=> ai.openai_embed('text-embedding-3-small', 'search query') + LIMIT 5; + ``` + + **After** — generate the embedding in Python, pass it to the query: + + ```python + import openai + import psycopg2 + + client = openai.OpenAI() # uses OPENAI_API_KEY env var + + def semantic_search(query: str, limit: int = 5): + # Generate the embedding in your application + response = client.embeddings.create( + model="text-embedding-3-small", + input=query, + ) + embedding = response.data[0].embedding + + # Pass the embedding as a parameter to the query + conn = psycopg2.connect("postgres://tsdbadmin:@:/tsdb?sslmode=require") + cur = conn.cursor() + cur.execute( + """ + SELECT id, content + FROM documents + ORDER BY embedding <=> %s::vector + LIMIT %s + """, + (embedding, limit), + ) + return cur.fetchall() + ``` + + Or with `asyncpg`: + + ```python + import openai + import asyncpg + + client = openai.OpenAI() + + async def semantic_search(query: str, limit: int = 5): + response = client.embeddings.create( + model="text-embedding-3-small", + input=query, + ) + embedding = response.data[0].embedding + + conn = await asyncpg.connect("postgres://tsdbadmin:@:/tsdb?sslmode=require") + rows = await conn.fetch( + """ + SELECT id, content + FROM documents + ORDER BY embedding <=> $1::vector + LIMIT $2 + """, + str(embedding), + limit, + ) + return rows + ``` + +- Migrate chat completion calls + + **Before** — chat completion inside the database: + + ```sql + SELECT ai.openai_chat_complete( + 'gpt-4o', + jsonb_build_array( + jsonb_build_object('role', 'user', 'content', 'Summarize this: ' || doc.content) + ) + )->'choices'->0->'message'->>'content' AS summary + FROM documents doc + WHERE doc.id = 1; + ``` + + **After** — call the API from your application: + + ```python + import openai + + client = openai.OpenAI() + + def summarize(content: str) -> str: + response = client.chat.completions.create( + model="gpt-4o", + messages=[{"role": "user", "content": f"Summarize this: {content}"}], + ) + return response.choices[0].message.content + ``` + +- Migrate Anthropic calls + + **Before:** + + ```sql + SELECT ai.anthropic_generate( + 'claude-sonnet-4-20250514', + jsonb_build_array( + jsonb_build_object('role', 'user', 'content', 'Explain this concept') + ) + ); + ``` + + **After:** + + ```python + import anthropic + + client = anthropic.Anthropic() + + def generate(prompt: str) -> str: + message = client.messages.create( + model="claude-sonnet-4-20250514", + max_tokens=1024, + messages=[{"role": "user", "content": prompt}], + ) + return message.content[0].text + ``` + +- Migrate Cohere reranking + + **Before:** + + ```sql + SELECT ai.cohere_rerank( + 'rerank-english-v3.0', + 'search query', + jsonb_agg(content) ) - return response.results -``` + FROM documents + LIMIT 100; + ``` + + **After:** + + ```python + import cohere + + client = cohere.Client() + + def rerank(query: str, documents: list[str]) -> list: + response = client.rerank( + model="rerank-english-v3.0", + query=query, + documents=documents, + ) + return response.results + ``` + + ### Summary of function replacements @@ -351,12 +359,18 @@ def rerank(query: str, documents: list[str]) -> list: For any `ai.*` function call: -1. **Identify the provider** — the function prefix tells you (`openai_`, `anthropic_`, `ollama_`, `cohere_`, `voyageai_`) -2. **Install the provider's Python SDK** — `pip install openai`, `pip install anthropic`, etc. -3. **Move the call to your application** — call the SDK from your app code before or after your database queries -4. **Pass results as query parameters** — for embeddings, generate the vector in your app and pass it as a parameter to your SQL query + + +1. **Identify the provider** — the function prefix tells you (`openai_`, `anthropic_`, `ollama_`, `cohere_`, `voyageai_`). +1. **Install the provider's Python SDK** — `pip install openai`, `pip install anthropic`, and so on. +1. **Move the call to your application** — call the SDK from your app code before or after your database queries. +1. **Pass results as query parameters** — for embeddings, generate the vector in your app and pass it as a parameter to your SQL query. + + [pgvector]: https://github.com/pgvector/pgvector [pgvectorscale]: https://github.com/timescale/pgvectorscale [pg_textsearch]: https://github.com/timescale/pg_textsearch +[migrate-the-vectorizer]: /ai/:currentVersion:/vectorizer-deprecation/#migrate-the-vectorizer +[connection-string]: /integrations/:currentVersion:/find-connection-details/ [pgai-worker-docs]: https://github.com/timescale/pgai/blob/main/docs/vectorizer/worker.md From 3c1c73e17a4ade41ef6069056a562beda7f11486 Mon Sep 17 00:00:00 2001 From: atovpeko Date: Mon, 23 Mar 2026 15:36:24 +0800 Subject: [PATCH 3/4] changelog --- about/changelog.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/about/changelog.md b/about/changelog.md index 336ccec9f1..494c5b709c 100644 --- a/about/changelog.md +++ b/about/changelog.md @@ -9,6 +9,17 @@ products: [cloud] All the latest features and updates to $CLOUD_LONG. +## Support cases in Tiger Console + + +You can now view and manage your support cases directly in Tiger Console. Open the `Support` tab at the project level to: + +- View all support cases for your project from the last 90 days +- Read the full email conversation thread +- Reply to open cases +- Close open cases + + ## Support for Azure Monitor From 70bdc5c1028a055c3e1cf4773ced9d262d4f7879 Mon Sep 17 00:00:00 2001 From: atovpeko Date: Mon, 23 Mar 2026 16:21:50 +0800 Subject: [PATCH 4/4] changelog --- _partials/_migrate_open_support_request.md | 2 +- _partials/_support-plans.md | 7 ++++++- about/changelog.md | 1 + use-timescale/data-tiering/enabling-data-tiering.md | 6 ++++++ use-timescale/services/service-overview.md | 2 ++ 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/_partials/_migrate_open_support_request.md b/_partials/_migrate_open_support_request.md index 776f91fa62..b8358ac996 100644 --- a/_partials/_migrate_open_support_request.md +++ b/_partials/_migrate_open_support_request.md @@ -1,4 +1,4 @@ You can open a support request directly from [$CONSOLE_LONG][open-support-ticket], or by email to [support@tigerdata.com](mailto:support@tigerdata.com). -[open-support-ticket]: https://console.cloud.timescale.com/dashboard/support +[open-support-ticket]: https://console.cloud.timescale.com/dashboard/support/cases diff --git a/_partials/_support-plans.md b/_partials/_support-plans.md index 55a18af62b..bcee0026e7 100644 --- a/_partials/_support-plans.md +++ b/_partials/_support-plans.md @@ -3,7 +3,12 @@ Support covers all timezones and is fully staffed at weekend hours. All paid $PRICING_PLANs have free Developer Support through email with a target response time of 1 business day; we are often faster. If you need 24x7 responsiveness, talk to us about -[Production Support][production-support]. With Production Support, you can request help at any time at our [Support portal][support-portal]. +[Production Support][production-support]. + +You can open, view, reply to, and close support tickets from the `Support` tab in $CONSOLE_LONG: + +![Manage support in Tiger Cloud](https://assets.timescale.com/docs/images/tiger-cloud-manage-support.png) + [production-support]: https://www.tigerdata.com/support [support-portal]: https://portal.support.timescale.com/login diff --git a/about/changelog.md b/about/changelog.md index 494c5b709c..4fc2111787 100644 --- a/about/changelog.md +++ b/about/changelog.md @@ -19,6 +19,7 @@ You can now view and manage your support cases directly in Tiger Console. Open t - Reply to open cases - Close open cases +![Manage support in Tiger Cloud](https://assets.timescale.com/docs/images/tiger-cloud-manage-support.png) ## Support for Azure Monitor diff --git a/use-timescale/data-tiering/enabling-data-tiering.md b/use-timescale/data-tiering/enabling-data-tiering.md index 77e56b3485..1f4a843746 100644 --- a/use-timescale/data-tiering/enabling-data-tiering.md +++ b/use-timescale/data-tiering/enabling-data-tiering.md @@ -268,6 +268,12 @@ To drop tiered data, call [DROP_TABLE][drop-hypertable] on the corresponding hyp ### Disable tiering + + +Contact $COMPANY support if you are disabling tiering when moving from $SCALE to $PERFORMANCE $PRICING_PLAN. + + + If you no longer want to use tiered storage for a particular hypertable, drop the associated metadata by calling `disable_tiering`. diff --git a/use-timescale/services/service-overview.md b/use-timescale/services/service-overview.md index 0517793c53..03c2bb4610 100644 --- a/use-timescale/services/service-overview.md +++ b/use-timescale/services/service-overview.md @@ -23,6 +23,7 @@ You use $CONSOLE_LONG to manage your $SERVICE_SHORTs and data in a convenient, c - `CLI/MCP`: install $CLI_LONG and set up $MCP_LONG. - `Users`: [add and remove users][members] in your $PROJECT_SHORT. - `Billing`: [check usage][check-usage], [change $PRICING_PLANs][pricing], and manage payment methods. +- `Support`: open and manage [support tickets][support-tickets]. When you select a $SERVICE_LONG in the `Services` tab, you land in the $OPS_MODE. In this view, you manage your $SERVICE_SHORTs. You see `Overview` and other related tabs: @@ -67,3 +68,4 @@ To query your $SERVICE_SHORT from any tab, click `SQL Editor` at the bottom. The [ip-allowlist]: /use-timescale/:currentVersion:/security/ip-allow-list/ [manage-extensions]: /use-timescale/:currentVersion:/extensions/ [activity-log]: /about/:currentVersion:/changelog#activity-log +[support-tickets]: /about/:currentVersion:/pricing-and-account-management#tiger-cloud-support \ No newline at end of file