From 540ee7f831523bb7b4b1bdb212676cc030f135ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Urba=C5=84ski?= Date: Fri, 13 Dec 2024 10:43:41 +0000 Subject: [PATCH 1/7] Add pgvector docker compose for local setup --- docker-compose.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..06e0f45 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +# Compose a postgres database together with the extension pgvector +services: + db: + hostname: db + image: ankane/pgvector + ports: + - 5555:5432 + restart: always + environment: + - POSTGRES_DB=vectordb + - POSTGRES_USER=testuser + - POSTGRES_PASSWORD=testpwd + - POSTGRES_HOST_AUTH_METHOD=trust + volumes: + - ./init.sql:/docker-entrypoint-initdb.d/init.sql \ No newline at end of file From 24b26278deb6a62a79645e0c31e456170704da00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Urba=C5=84ski?= Date: Fri, 13 Dec 2024 11:21:22 +0000 Subject: [PATCH 2/7] Add saving csv data to pgvector --- dockers/llm.vdb.service/common.py | 39 ++++++++++++++++++ .../createvectordb_csv_to_pgvector_local.py | 41 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 dockers/llm.vdb.service/createvectordb_csv_to_pgvector_local.py diff --git a/dockers/llm.vdb.service/common.py b/dockers/llm.vdb.service/common.py index e548794..b274af9 100644 --- a/dockers/llm.vdb.service/common.py +++ b/dockers/llm.vdb.service/common.py @@ -1,5 +1,6 @@ import json import os +from typing import List from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.vectorstores import FAISS @@ -79,3 +80,41 @@ def create_vectordb( print("Convert to FAISS vectorstore") vectorstore = FAISS.from_texts(texts, embeddings, metadatas=metadatas) return vectorstore + + +def create_vectordb_pgvector( + local_tmp_dir: str, + embedding_model_name: str, + connection_string: str, + collection_name: str, + chunk_size: int = EMBEDDING_CHUNK_SIZE_DEFAULT, + chunk_overlap: int = EMBEDDING_CHUNK_OVERLAP_DEFAULT, +): + data = load_jsonl_files_from_directory(local_tmp_dir) + + # no chunking + # texts, metadatas = get_documents_with_metadata(data) + # with chunking texts + texts, metadatas = chunk_documents_with_metadata(data, chunk_size, chunk_overlap) + + embeddings = HuggingFaceEmbeddings(model_name=embedding_model_name) + + # TODO: move to imports + from langchain.vectorstores.pgvector import PGVector + from langchain_core.documents import Document + + # adapt data + documents: List[Document] = [] + for txt, met in zip(texts, metadatas): + document = Document( + page_content=txt, + metadata=met + ) + documents.append(document) + + return PGVector.from_documents( + embedding=embeddings, + documents=documents, + collection_name=collection_name, + connection_string=connection_string, + ) diff --git a/dockers/llm.vdb.service/createvectordb_csv_to_pgvector_local.py b/dockers/llm.vdb.service/createvectordb_csv_to_pgvector_local.py new file mode 100644 index 0000000..2b688ce --- /dev/null +++ b/dockers/llm.vdb.service/createvectordb_csv_to_pgvector_local.py @@ -0,0 +1,41 @@ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "click", +# "langchain", +# "langchain-community", +# "langchain-huggingface", +# "pgvector", +# "psycopg2-binary", +# ] +# /// + +# Source: dockers/llm.vdb.service/createvectordb.py + +import click + +from common import create_vectordb_pgvector + + +@click.command() +@click.argument("local_tmp_dir", type=click.Path(exists=True)) +@click.argument( + "embedding_model_name", default="sentence-transformers/all-MiniLM-L6-v2" +) +def run(local_tmp_dir: str, embedding_model_name: str): + # TODO: pass through settings or params + connection_string = "postgresql+psycopg2://testuser:testpwd@localhost:5555/vectordb" + collection_name = "jira_tickets" + + db = create_vectordb_pgvector( + local_tmp_dir, + embedding_model_name, + connection_string, + collection_name, + ) + + print(f"Data saved to {db.collection_name}") + + +if __name__ == "__main__": + run() From 64ee9e3a4f7804a80c12da89fc88006ddc14c5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Urba=C5=84ski?= Date: Fri, 13 Dec 2024 11:41:37 +0000 Subject: [PATCH 3/7] Add rag app using pgvector --- .../serverragllm_csv_to_pgvector_local.py | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 dockers/llm.rag.service/serverragllm_csv_to_pgvector_local.py diff --git a/dockers/llm.rag.service/serverragllm_csv_to_pgvector_local.py b/dockers/llm.rag.service/serverragllm_csv_to_pgvector_local.py new file mode 100644 index 0000000..abbbbc8 --- /dev/null +++ b/dockers/llm.rag.service/serverragllm_csv_to_pgvector_local.py @@ -0,0 +1,108 @@ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "faiss-cpu", +# "fastapi", +# "langchain-community", +# "langchain-huggingface", +# "langchain-postgres", +# "openai", +# "psycopg2-binary", +# "uvicorn", +# ] +# /// + +import os +import pickle +import sys +import uvicorn + +from functools import partial +from typing import Union + +import click +from fastapi import FastAPI +from openai import OpenAI + +from common import get_answer_with_settings + + +def setup( + relevant_docs: int, + llm_server_url:str, + model_id: str, + max_tokens: int, + model_temperature: float, +): + app = FastAPI() + + # TODO: move to imports + from langchain.vectorstores.pgvector import PGVector + from langchain_huggingface import HuggingFaceEmbeddings + + # TODO: pass through settings or params + connection_string = "postgresql+psycopg2://testuser:testpwd@localhost:5555/vectordb" + collection_name = "jira_tickets" + embedding_model_name = "sentence-transformers/all-MiniLM-L6-v2" + + embeddings = HuggingFaceEmbeddings(model_name=embedding_model_name) + + vectorstore = PGVector( + connection_string=connection_string, + collection_name=collection_name, + embedding_function=embeddings + ) + + retriever = vectorstore.as_retriever(search_kwargs={"k": relevant_docs}) + print("Created Vector DB retriever successfully. \n") + + print("Creating an OpenAI client to the hosted model at URL: ", llm_server_url) + try: + client = OpenAI(base_url=llm_server_url, api_key="na") + except Exception as e: + print("Error creating client:", e) + sys.exit(1) + + get_answer = partial( + get_answer_with_settings, + retriever=retriever, + client=client, + model_id=model_id, + max_tokens=max_tokens, + model_temperature=model_temperature, + ) + + @app.get("/answer/{question}") + def read_item(question: Union[str, None] = None): + print(f"Received question: {question}") + answer = get_answer(question) + return {"question": question, "answer": answer} + + return app + + +MICROSOFT_MODEL_ID = "microsoft/Phi-3-mini-4k-instruct" +MOSAICML_MODEL_ID = "mosaicml/mpt-7b-chat" +RELEVANT_DOCS_DEFAULT = 2 +MAX_TOKENS_DEFAULT = 64 +MODEL_TEMPERATURE_DEFAULT = 0.01 + +relevant_docs = os.getenv("RELEVANT_DOCS", RELEVANT_DOCS_DEFAULT) +llm_server_url = os.getenv("LLM_SERVER_URL", "http://localhost:11434/v1") +model_id = os.getenv("MODEL_ID", "llama2") +max_tokens = int(os.getenv("MAX_TOKENS", MAX_TOKENS_DEFAULT)) +model_temperature = float(os.getenv("MODEL_TEMPERATURE", MODEL_TEMPERATURE_DEFAULT)) + +app = setup(relevant_docs, llm_server_url, model_id, max_tokens, model_temperature) + + +@click.command() +@click.option("--host", default="127.0.0.1", help="Host for the FastAPI server (default: 127.0.0.1)") +@click.option("--port", type=int, default=8000, help="Port for the FastAPI server (default: 8000)") +def run(host, port): + # Serve the app using Uvicorn + uvicorn.run("serverragllm_csv_to_pgvector_local:app", host=host, port=port, reload=True) + + +if __name__ == "__main__": + run() From 64f9cf6f2ecb32bfe3d64e9420beb06ee661d0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Urba=C5=84ski?= Date: Fri, 13 Dec 2024 12:18:09 +0000 Subject: [PATCH 4/7] Fix deprecation warnings --- .../llm.rag.service/serverragllm_csv_to_pgvector_local.py | 8 ++++---- dockers/llm.vdb.service/common.py | 4 ++-- .../createvectordb_csv_to_pgvector_local.py | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/dockers/llm.rag.service/serverragllm_csv_to_pgvector_local.py b/dockers/llm.rag.service/serverragllm_csv_to_pgvector_local.py index abbbbc8..fb82d14 100644 --- a/dockers/llm.rag.service/serverragllm_csv_to_pgvector_local.py +++ b/dockers/llm.rag.service/serverragllm_csv_to_pgvector_local.py @@ -13,7 +13,6 @@ # /// import os -import pickle import sys import uvicorn @@ -37,7 +36,7 @@ def setup( app = FastAPI() # TODO: move to imports - from langchain.vectorstores.pgvector import PGVector + from langchain_postgres import PGVector from langchain_huggingface import HuggingFaceEmbeddings # TODO: pass through settings or params @@ -48,9 +47,10 @@ def setup( embeddings = HuggingFaceEmbeddings(model_name=embedding_model_name) vectorstore = PGVector( - connection_string=connection_string, + embeddings=embeddings, collection_name=collection_name, - embedding_function=embeddings + connection=connection_string, + use_jsonb=True, ) retriever = vectorstore.as_retriever(search_kwargs={"k": relevant_docs}) diff --git a/dockers/llm.vdb.service/common.py b/dockers/llm.vdb.service/common.py index b274af9..e35e212 100644 --- a/dockers/llm.vdb.service/common.py +++ b/dockers/llm.vdb.service/common.py @@ -100,7 +100,7 @@ def create_vectordb_pgvector( embeddings = HuggingFaceEmbeddings(model_name=embedding_model_name) # TODO: move to imports - from langchain.vectorstores.pgvector import PGVector + from langchain_postgres import PGVector from langchain_core.documents import Document # adapt data @@ -116,5 +116,5 @@ def create_vectordb_pgvector( embedding=embeddings, documents=documents, collection_name=collection_name, - connection_string=connection_string, + connection=connection_string, ) diff --git a/dockers/llm.vdb.service/createvectordb_csv_to_pgvector_local.py b/dockers/llm.vdb.service/createvectordb_csv_to_pgvector_local.py index 2b688ce..2676e32 100644 --- a/dockers/llm.vdb.service/createvectordb_csv_to_pgvector_local.py +++ b/dockers/llm.vdb.service/createvectordb_csv_to_pgvector_local.py @@ -5,6 +5,7 @@ # "langchain", # "langchain-community", # "langchain-huggingface", +# "langchain_postgres", # "pgvector", # "psycopg2-binary", # ] From 9031e8b6d406894ce0e1a44ca35f7cbb5ba97f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Urba=C5=84ski?= Date: Fri, 13 Dec 2024 12:24:03 +0000 Subject: [PATCH 5/7] Comment --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index 06e0f45..17a252d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,5 @@ # Compose a postgres database together with the extension pgvector +# source: https://github.com/johannesocean/pgvector-demo/blob/main/docker-compose.yml services: db: hostname: db From 635cb0f784260ce26f55b986e646e638160dba1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Urba=C5=84ski?= Date: Tue, 7 Jan 2025 12:53:18 +0000 Subject: [PATCH 6/7] Add files to docker image --- dockers/llm.rag.service/Dockerfile | 1 + dockers/llm.vdb.service/Dockerfile | 1 + 2 files changed, 2 insertions(+) diff --git a/dockers/llm.rag.service/Dockerfile b/dockers/llm.rag.service/Dockerfile index 9f8e478..06168a7 100644 --- a/dockers/llm.rag.service/Dockerfile +++ b/dockers/llm.rag.service/Dockerfile @@ -43,6 +43,7 @@ RUN pip3 install --no-cache-dir \ COPY __init__.py . COPY serveragllm.py . COPY serverragllm_jira_cvs_local.py . +COPY serverragllm_csv_to_pgvector_local.py . COPY common.py . COPY pyproject.toml . diff --git a/dockers/llm.vdb.service/Dockerfile b/dockers/llm.vdb.service/Dockerfile index 8628d1d..8743a53 100644 --- a/dockers/llm.vdb.service/Dockerfile +++ b/dockers/llm.vdb.service/Dockerfile @@ -45,6 +45,7 @@ RUN pip3 install --no-cache-dir \ COPY __init__.py . COPY createvectordb.py . COPY createvectordb_jira_csv_local.py . +COPY createvectordb_csv_to_pgvector_local.py . COPY common.py . COPY pyproject.toml . From 32bf95be1d05d1d0aff5b5d2b47bca4fa9ce1862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Urba=C5=84ski?= Date: Thu, 9 Jan 2025 12:50:50 +0000 Subject: [PATCH 7/7] Remove files that are not needed inside docker --- dockers/llm.rag.service/Dockerfile | 2 -- dockers/llm.vdb.service/Dockerfile | 2 -- 2 files changed, 4 deletions(-) diff --git a/dockers/llm.rag.service/Dockerfile b/dockers/llm.rag.service/Dockerfile index 06168a7..4bc063a 100644 --- a/dockers/llm.rag.service/Dockerfile +++ b/dockers/llm.rag.service/Dockerfile @@ -42,8 +42,6 @@ RUN pip3 install --no-cache-dir \ COPY __init__.py . COPY serveragllm.py . -COPY serverragllm_jira_cvs_local.py . -COPY serverragllm_csv_to_pgvector_local.py . COPY common.py . COPY pyproject.toml . diff --git a/dockers/llm.vdb.service/Dockerfile b/dockers/llm.vdb.service/Dockerfile index 8743a53..a2019dd 100644 --- a/dockers/llm.vdb.service/Dockerfile +++ b/dockers/llm.vdb.service/Dockerfile @@ -44,8 +44,6 @@ RUN pip3 install --no-cache-dir \ COPY __init__.py . COPY createvectordb.py . -COPY createvectordb_jira_csv_local.py . -COPY createvectordb_csv_to_pgvector_local.py . COPY common.py . COPY pyproject.toml .