Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class SelfCorrectingRAG:
]

def __init__(self, input_dir: str, similarity_top_k: int = 3, chunk_size: int = 128,
chunk_overlap: int = 100, show_progress: bool = False, no_of_retries: int = 5, required_exts: list[str] = ['.pdf', '.txt']):
chunk_overlap: int = 100, show_progress: bool = False, no_of_retries: int = 5,
required_exts: list[str] = ['.pdf', '.txt']):

self.input_dir = input_dir
self.similarity_top_k = similarity_top_k
Expand Down Expand Up @@ -108,7 +109,8 @@ def query_with_retry_query_engine(self, query: str) -> RESPONSE_TYPE:
# source nodes for the query based on llm node evaluation.
def query_with_source_query_engine(self, query: str) -> RESPONSE_TYPE:
retry_source_query_engine = RetrySourceQueryEngine(self.base_query_engine,
self.query_response_evaluator)
self.query_response_evaluator,
max_retries=self.no_of_retries)
retry_source_response = retry_source_query_engine.query(query)
return retry_source_response

Expand All @@ -121,6 +123,7 @@ def query_with_guideline_query_engine(self, query: str) -> RESPONSE_TYPE:
"The response should try to summarize where possible.\n"
) # just for example
retry_guideline_query_engine = RetryGuidelineQueryEngine(self.base_query_engine,
guideline_eval, resynthesize_query=True)
guideline_eval, resynthesize_query=True,
max_retries=self.no_of_retries)
retry_guideline_response = retry_guideline_query_engine.query(query)
return retry_guideline_response
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.vector_stores.qdrant import QdrantVectorStore
from llama_index. core. base. base_query_engine import BaseQueryEngine
from llama_index.core.base.response.schema import Response, StreamingResponse, AsyncStreamingResponse, PydanticResponse
from llama_index.core.query_engine import RetryQueryEngine, RetrySourceQueryEngine, RetryGuidelineQueryEngine
from llama_index.core.evaluation import RelevancyEvaluator, GuidelineEvaluator
Expand Down Expand Up @@ -68,8 +69,8 @@ def __init__(self, input_dir: str, similarity_top_k: int = 3, chunk_size: int =
api_key=os.environ['DB_API_KEY'])
self.vector_store = QdrantVectorStore(client=self.client, collection_name=os.environ['COLLECTION_NAME'])
self.query_response_evaluator = RelevancyEvaluator()
self.base_query_engine = None
self._index = None
self.base_query_engine: BaseQueryEngine = None
self._index: VectorStoreIndex = None

self._load_data_and_create_engine()

Expand Down
5 changes: 5 additions & 0 deletions bootstraprag/templates/qdrant/hybrid_search/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DB_URL='http://localhost:6333'
DB_API_KEY=''
COLLECTION_NAME='YOUR_COLLECTION'
DENSE_MODEL='sentence-transformers/all-MiniLM-L6-v2'
SPARSE_MODEL='prithivida/Splade_PP_en_v1'
Empty file.
22,000 changes: 22,000 additions & 0 deletions bootstraprag/templates/qdrant/hybrid_search/data/startups-mini.json

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions bootstraprag/templates/qdrant/hybrid_search/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import os

from search import HybridSearch
from dotenv import find_dotenv, load_dotenv

_ = load_dotenv(find_dotenv())

simple_search = HybridSearch(collection_name=os.environ['COLLECTION_NAME'])

# uncomment if you want to index the data for the first time
# simple_search.insert()
result = simple_search.search(input_text='San Francisco')

print(result)
29 changes: 29 additions & 0 deletions bootstraprag/templates/qdrant/hybrid_search/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## What is this project all about

this is a boot straped project using bootstrap-rag cli tool. This project assume you have docker for desktop installed in your machine.

### Project scafolding
```
.
├── __init__.py
├── __pycache__
├── .env
├── main.py
├── readme.md
├── requirements.txt
└── search.py
```
- docker-compose.yml: if your machine does not have qdrant installed don't worry run this `docker-compose-dev.yml` in setups folder
- `docker-compose -f docker-compose-dev.yml up -d`
- requirements.txt: this file has all the dependencies that a project need
- search.py: the core logic is present in this file
- main.py: this is the driver code to test.

### How to bring in your own custom logics
- open `search.py` and modify your `insert` and `query` functions.

or

- create a `new_search_file.py` and extend it from `search.py` then override the base functionality in the new one.


3 changes: 3 additions & 0 deletions bootstraprag/templates/qdrant/hybrid_search/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
qdrant-client==1.11.1
python-dotenv==1.0.1
fastembed==0.3.6
68 changes: 68 additions & 0 deletions bootstraprag/templates/qdrant/hybrid_search/search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import os
import json
from tqdm import tqdm
from qdrant_client import qdrant_client, models
from dotenv import find_dotenv, load_dotenv
from qdrant_client.http.models import Distance
from qdrant_client.conversions.common_types import QueryResponse, UpdateResult


class HybridSearch:
_ = load_dotenv(find_dotenv())

def __init__(self, collection_name: str, vector_dimension: int = 384, distance: Distance = models.Distance.COSINE):
self.client = qdrant_client.QdrantClient(url=os.environ['DB_URL'], api_key=os.environ['DB_API_KEY'])

# set the dense and sparse embedding models
self.client.set_model(os.environ.get('DENSE_MODEL'))
self.vector_dimension = vector_dimension
self.distance = distance
self.collection_name = collection_name

self.documents = []
self.metadata = []

# create collection call
self._create_collection(collection_name=collection_name)

def _create_collection(self, collection_name):
if not self.client.collection_exists(collection_name=collection_name):
self.client.create_collection(
collection_name=collection_name,
vectors_config=self.client.get_fastembed_vector_params(),
sparse_vectors_config=self.client.get_fastembed_sparse_vector_params()
)

def _read_data(self):
payload_path = "data/startups-mini.json"

with open(payload_path) as fd:
for line in fd:
obj = json.loads(line)
self.documents.append(obj.pop("description"))
self.metadata.append(obj)

def insert(self) -> UpdateResult:
self._read_data()
# simple boilerplate code adjust it accordingly
self.client.add(
collection_name=self.collection_name,
documents=self.documents,
metadata=self.metadata,
batch_size=128, # a batch os 128 embeddings will be pushed in a single request
ids=tqdm(range(len(self.documents)))
)

def search(self, input_text: str) -> QueryResponse:
search_result = self.client.query(
collection_name=self.collection_name,
query_text=input_text,
query_filter=None, # If you don't want any filters for now
limit=5, # 5 the closest results
)
# `search_result` contains found vector ids with similarity scores
# along with the stored payload

# Select and return metadata
metadata = [hit.metadata for hit in search_result]
return metadata # if not return entire search_result
1 change: 1 addition & 0 deletions bootstraprag/templates/qdrant/simple_search/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
DB_URL='http://localhost:6333'
DB_API_KEY=''
COLLECTION_NAME='YOUR_COLLECTION'
DENSE_MODEL='sentence-transformers/all-MiniLM-L6-v2'
Loading