From 91a4385e032c355d882b4837c455241c0a98eace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=9A=D1=83=D1=82?= =?UTF-8?q?=D0=BB=D0=B0=D1=85=D0=BC=D0=B5=D1=82=D0=BE=D0=B2?= Date: Thu, 28 May 2026 09:27:16 +0000 Subject: [PATCH] add vector_store.py --- vector_store.py | 79 +++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 45 deletions(-) diff --git a/vector_store.py b/vector_store.py index d5e6872..912c70a 100644 --- a/vector_store.py +++ b/vector_store.py @@ -1,21 +1,18 @@ """ -Vector store implementation using ChromaDB. +Vector store abstraction using ChromaDB. -Provides functions to add documents and perform semantic search. +Provides methods to add documents with embeddings and perform similarity search. """ - import os -from typing import List, Dict -from langchain_ollama import OllamaEmbeddings -from chromadb import Client +from pathlib import Path +from typing import List, Dict, Any + +from chromadb import Client as ChromaClient from chromadb.config import Settings +from langchain_ollama import OllamaEmbeddings -# Initialize embeddings model (Ollama) -embeddings = OllamaEmbeddings(model="nomic-embed-text") - -# ChromaDB client – in‑memory by default, persistent folder "chromadb" -CHROMA_DIR = os.path.join(os.getcwd(), "chromadb") -client = Client(Settings(chroma_db_impl="duckdb+parquet", persist_directory=CHROMA_DIR)) +# Initialize global client (in-memory for simplicity) +client = ChromaClient(Settings(chroma_db_impl="duckdb+parquet", persist_directory=None)) collection_name = "rag_collection" # Ensure collection exists @@ -23,43 +20,35 @@ if collection_name not in client.list_collections(): client.create_collection(name=collection_name) col = client.get_or_create_collection(name=collection_name) -class VectorStore: +embeddings = OllamaEmbeddings(model="nomic-embed-text") + +class ChromaVectorStore: + """Wrapper around a Chroma collection.""" + def __init__(self, collection): self.collection = collection - def add_document(self, doc_id: str, text: str, metadata: Dict | None = None) -> None: - """Add a single document to the collection. + def add_documents(self, documents: List[Dict[str, Any]]): + ids = [] + texts = [] + metadatas = [] + for doc in documents: + ids.append(doc.get("id", os.urandom(8).hex())) + texts.append(doc["content"]) + metadatas.append(doc.get("metadata", {})) + embeddings_list = embeddings.embed_documents(texts) + self.collection.add(ids=ids, documents=texts, embeddings=embeddings_list, metadatas=metadatas) - Parameters - ---------- - doc_id: str - Unique identifier for the document. - text: str - Raw text content. - metadata: dict, optional - Additional key/value pairs stored with the vector. - """ - vec = embeddings.embed_query(text) - self.collection.add(ids=[doc_id], documents=[text], metadatas=[metadata or {}]) - - def search(self, query: str, k: int = 5) -> List[Dict]: - """Semantic search over the collection. - - Returns a list of dicts with keys: id, document, score, metadata. - """ + def similarity_search(self, query: str, k: int = 5) -> List[Dict[str, Any]]: results = self.collection.query( - query_texts=[query], n_results=k, include=['documents', 'distances', 'metadatas'] + query_texts=[query], + n_results=k, + include=['documents', 'distances', 'metadatas'], ) - hits = [] - for i in range(len(results["ids"][0])): - hit = { - "id": results["ids"][0][i], - "document": results["documents"][0][i], - "score": 1 - results["distances"][0][i], # distance to similarity - "metadata": results["metadatas"][0][i], - } - hits.append(hit) - return hits + docs = [] + for doc, dist, meta in zip(results["documents"][0], results["distances"][0], results["metadatas"][0]): + docs.append({"content": doc, "distance": dist, "metadata": meta}) + return docs -# Singleton instance for easy import -vector_store = VectorStore(col) +# Singleton instance +vector_store = ChromaVectorStore(col)