diff --git a/db.Dockerfile b/db.Dockerfile new file mode 100644 index 0000000000..99db7497fb --- /dev/null +++ b/db.Dockerfile @@ -0,0 +1,11 @@ +FROM postgres:16-alpine3.24 + +# Install pgvector extension https://github.com/pgvector/pgvector#installation +RUN apk add --no-cache --virtual .build-deps \ + git build-base clang21 llvm21 && \ + cd /tmp && \ + git clone --branch v0.8.6 https://github.com/pgvector/pgvector.git && \ + cd pgvector && \ + make && \ + make install && \ + apk del .build-deps diff --git a/docker-compose.yml b/docker-compose.yml index f72af94504..592953a738 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,7 +56,9 @@ services: - spark - test - usaspending - image: postgres:16-alpine + build: + context: . + dockerfile: db.Dockerfile healthcheck: test: [ "CMD-SHELL", "pg_isready -U ${USASPENDING_DB_USER} -d ${USASPENDING_DB_NAME}" ] interval: 5s diff --git a/pyproject.toml b/pyproject.toml index 1be1e8536a..d43f2f0b73 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ dependencies = [ "numpy==1.26.*", "openpyxl==3.1.*", "pandas==2.2.*", + "pgvector>=0.5.0", "psutil==5.9.*", "psycopg>=3.3.3", "py-gfm==2.0.0", diff --git a/usaspending_api/llm/migrations/0002_create_pgvector.py b/usaspending_api/llm/migrations/0002_create_pgvector.py new file mode 100644 index 0000000000..c77999035b --- /dev/null +++ b/usaspending_api/llm/migrations/0002_create_pgvector.py @@ -0,0 +1,9 @@ +from django.db import migrations +from pgvector.django import VectorExtension + + +class Migration(migrations.Migration): + + dependencies = [("llm", "0001_initial")] + + operations = [VectorExtension()] diff --git a/uv.lock b/uv.lock index d34a6f8344..5590d8f050 100644 --- a/uv.lock +++ b/uv.lock @@ -1343,6 +1343,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/31/9e/6ebb433de864a6cd45716af52a4d7a8c3c9aaf3a98368e61db9e69e69a9c/pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645", size = 11598471, upload-time = "2024-09-20T13:08:53.332Z" }, ] +[[package]] +name = "pgvector" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/ec/6eb80aebc728200f95229219882994c1b0585b956ca47da5edb9d062627a/pgvector-0.5.0.tar.gz", hash = "sha256:07a9dcf735696879406983afc6eba9a787cef7c0cf6c367ca1a5779f036dee74", size = 35170, upload-time = "2026-07-06T18:27:27.767Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/e4/a5573f2c579ca9ad133293bfb624148ba0893674ca4a6eeec85ced9a6a09/pgvector-0.5.0-py3-none-any.whl", hash = "sha256:fedc9800894e6da2be51358d7b7c574bf34f247ca741a5a09513622135f5964f", size = 30958, upload-time = "2026-07-06T18:27:26.797Z" }, +] + [[package]] name = "pip" version = "23.2.1" @@ -1965,6 +1974,7 @@ dependencies = [ { name = "opentelemetry-semantic-conventions" }, { name = "opentelemetry-util-http" }, { name = "pandas" }, + { name = "pgvector" }, { name = "psutil" }, { name = "psycopg" }, { name = "py-gfm" }, @@ -2090,6 +2100,7 @@ requires-dist = [ { name = "opentelemetry-util-http", specifier = "==0.49b2" }, { name = "packaging", marker = "extra == 'server'", specifier = "==22.0" }, { name = "pandas", specifier = "==2.2.*" }, + { name = "pgvector", specifier = ">=0.5.0" }, { name = "pip", marker = "extra == 'dev'", specifier = "==23.2.*" }, { name = "pre-commit", marker = "extra == 'dev'", specifier = "==3.6.2" }, { name = "psutil", specifier = "==5.9.*" },