Skip to content

Commit cf78325

Browse files
authored
feat: add hybrid search for retrieval (#7)
Adds hybrid search capability to the rag. Default retrieval ist hybrid mode.
1 parent 5f3884d commit cf78325

File tree

9 files changed

+430
-73
lines changed

9 files changed

+430
-73
lines changed

rag-core-api/poetry.lock

+341-35
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rag-core-api/pyproject.toml

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ langgraph = "^0.2.23"
2828
pillow = "^11.0.0"
2929
langchain-ollama = "^0.2.0"
3030
pytest-asyncio = "^0.25.0"
31+
langchain-community = "0.3.19"
32+
fastembed = "^0.6.0"
3133

3234
[tool.poetry.group.dev.dependencies]
3335
debugpy = "^1.8.1"

rag-core-api/src/rag_core_api/dependency_container.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from langchain_community.llms.fake import FakeListLLM
1717
from langchain_ollama import ChatOllama
1818
from langchain_openai import ChatOpenAI
19-
from langchain_qdrant import QdrantVectorStore
19+
from langchain_qdrant import QdrantVectorStore, FastEmbedSparse
2020
from langfuse import Langfuse
2121

2222
from rag_core_api.impl.answer_generation_chains.answer_generation_chain import (
@@ -50,6 +50,7 @@
5050
from rag_core_api.impl.settings.ragas_settings import RagasSettings
5151
from rag_core_api.impl.settings.reranker_settings import RerankerSettings
5252
from rag_core_api.impl.settings.retriever_settings import RetrieverSettings
53+
from rag_core_api.impl.settings.sparse_embedder_settings import SparseEmbedderSettings
5354
from rag_core_api.impl.settings.stackit_embedder_settings import StackitEmbedderSettings
5455
from rag_core_api.impl.settings.vector_db_settings import VectorDatabaseSettings
5556
from rag_core_api.impl.vector_databases.qdrant_database import QdrantDatabase
@@ -95,6 +96,7 @@ class DependencyContainer(DeclarativeContainer):
9596
embedder_class_type_settings = EmbedderClassTypeSettings()
9697
stackit_embedder_settings = StackitEmbedderSettings()
9798
chat_history_settings = ChatHistorySettings()
99+
sparse_embedder_settings = SparseEmbedderSettings()
98100
chat_history_config.from_dict(chat_history_settings.model_dump())
99101

100102
class_selector_config.from_dict(rag_class_type_settings.model_dump() | embedder_class_type_settings.model_dump())
@@ -110,22 +112,28 @@ class DependencyContainer(DeclarativeContainer):
110112
),
111113
)
112114

115+
sparse_embedder = Singleton(FastEmbedSparse, **sparse_embedder_settings.model_dump())
116+
113117
vectordb_client = Singleton(
114118
qdrant_client.QdrantClient,
115119
location=vector_database_settings.location,
116120
)
121+
117122
vectorstore = Singleton(
118123
QdrantVectorStore,
119124
client=vectordb_client,
120125
collection_name=vector_database_settings.collection_name,
121126
embedding=embedder,
127+
sparse_embedding=sparse_embedder,
122128
validate_collection_config=False,
129+
retrieval_mode=vector_database_settings.retrieval_mode,
123130
)
124131

125132
vector_database = Singleton(
126133
QdrantDatabase,
127134
settings=vector_database_settings,
128135
embedder=embedder,
136+
sparse_embedder=sparse_embedder,
129137
vectorstore=vectorstore,
130138
)
131139

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Module contains settings regarding the sparse embedder."""
2+
3+
from pydantic import Field
4+
from pydantic_settings import BaseSettings
5+
6+
7+
class SparseEmbedderSettings(BaseSettings):
8+
"""
9+
Contains settings regarding the sparse embedder.
10+
11+
Attributes
12+
----------
13+
model_name : str
14+
The name of the model to be used (default "Qdrant/bm25").
15+
"""
16+
17+
class Config:
18+
"""Config class for reading Fields from env."""
19+
20+
env_prefix = "SPARSE_EMBEDDER_"
21+
case_sensitive = False
22+
23+
model_name: str = Field(default="Qdrant/bm25")

rag-core-api/src/rag_core_api/impl/settings/vector_db_settings.py

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from pydantic_settings import BaseSettings
44
from pydantic import Field
55

6+
from langchain_qdrant import RetrievalMode
7+
68

79
class VectorDatabaseSettings(BaseSettings):
810
"""
@@ -27,3 +29,4 @@ class Config:
2729
validate_collection_config: bool = Field(
2830
default=False
2931
) # if true and collection does not exist, an error will be raised
32+
retrieval_mode: RetrievalMode = Field(default=RetrievalMode.HYBRID)

rag-core-api/src/rag_core_api/impl/vector_databases/qdrant_database.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import logging
33

44
from langchain_core.documents import Document
5-
from langchain_qdrant import QdrantVectorStore
5+
from langchain_qdrant import QdrantVectorStore, SparseEmbeddings
66
from qdrant_client.http import models
77
from qdrant_client.models import FieldCondition, Filter, MatchValue
88

@@ -25,6 +25,7 @@ def __init__(
2525
self,
2626
settings: VectorDatabaseSettings,
2727
embedder: Embedder,
28+
sparse_embedder: SparseEmbeddings,
2829
vectorstore: QdrantVectorStore,
2930
):
3031
"""
@@ -43,6 +44,7 @@ def __init__(
4344
settings=settings,
4445
embedder=embedder,
4546
vectorstore=vectorstore,
47+
sparse_embedder=sparse_embedder,
4648
)
4749

4850
@property
@@ -167,9 +169,11 @@ def upload(self, documents: list[Document]) -> None:
167169
"""
168170
self._vectorstore = self._vectorstore.from_documents(
169171
documents,
170-
self._embedder.get_embedder(),
171-
collection_name=self._settings.collection_name,
172+
embedding=self._embedder.get_embedder(),
173+
sparse_embedding=self._sparse_embedder,
172174
location=self._settings.location,
175+
collection_name=self._settings.collection_name,
176+
retrieval_mode=self._settings.retrieval_mode,
173177
)
174178

175179
def delete(self, delete_request: dict) -> None:

rag-core-api/src/rag_core_api/vector_databases/vector_database.py

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from langchain_community.vectorstores import VectorStore
66
from langchain_core.documents import Document
7+
from langchain_qdrant import SparseEmbeddings
78

89
from rag_core_api.embeddings.embedder import Embedder
910
from rag_core_api.impl.settings.vector_db_settings import VectorDatabaseSettings
@@ -16,6 +17,7 @@ def __init__(
1617
self,
1718
settings: VectorDatabaseSettings,
1819
embedder: Embedder,
20+
sparse_embedder: SparseEmbeddings,
1921
vectorstore: VectorStore,
2022
):
2123
"""
@@ -32,6 +34,7 @@ def __init__(
3234
"""
3335
self._settings = settings
3436
self._embedder = embedder
37+
self._sparse_embedder = sparse_embedder
3538
self._vectorstore = vectorstore
3639

3740
@property

rag-core-lib/poetry.lock

+41-33
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rag-core-lib/pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ packages = [{ include = "rag_core_lib", from = "src" }]
1212
[tool.poetry.dependencies]
1313
python = "^3.11"
1414
langchain = "^0.3.7"
15-
langchain-community = "0.3.7"
15+
langchain-community = "0.3.19"
1616
flashrank = "^0.2.5"
1717
pydantic-settings = "^2.2.1"
1818
pydantic = "^2.7.2"

0 commit comments

Comments
 (0)