69 lines
2.9 KiB
Markdown
69 lines
2.9 KiB
Markdown
**What was implemented**
|
||
- Replaced the former ChromaDB vector store with **Qdrant**.
|
||
- Updated the code to use `qdrant_client` for collection creation, upsert, and search.
|
||
- Removed all Chroma imports and added the necessary Qdrant imports.
|
||
- Adjusted the dependency list (e.g., `qdrant-client` added, `chromadb` removed).
|
||
|
||
**Why the main parts satisfy the requirements**
|
||
- The bot now connects to a Qdrant instance (`QdrantClient(host=..., port=..., api_key=...)`) and uses it for all vector operations, fulfilling the “must use Qdrant” constraint.
|
||
- `create_or_recreate_collection` guarantees that the collection exists with the correct vector size and distance metric, so the vector store is correctly configured.
|
||
- `ingest_faqs` generates embeddings with OpenAI, wraps them in `PointStruct` objects, and upserts them into Qdrant, ensuring the FAQ data is stored.
|
||
- `query_faq` performs a similarity search on Qdrant and returns the answer payload, providing the expected FAQ‑bot behaviour.
|
||
|
||
**Short code excerpts**
|
||
|
||
*src/main.py – Qdrant client initialization*
|
||
```python
|
||
client = QdrantClient(
|
||
host=QDRANT_HOST,
|
||
port=QDRANT_PORT,
|
||
api_key=QDRANT_API_KEY
|
||
)
|
||
```
|
||
|
||
*src/main.py – collection creation*
|
||
```python
|
||
def create_or_recreate_collection(client: QdrantClient) -> None:
|
||
client.recreate_collection(
|
||
collection_name=COLLECTION_NAME,
|
||
vectors_config=qdrant_models.VectorParams(
|
||
size=EMBEDDING_DIM,
|
||
distance=qdrant_models.Distance.COSINE
|
||
)
|
||
)
|
||
```
|
||
|
||
*src/main.py – ingesting FAQs*
|
||
```python
|
||
def ingest_faqs(client: QdrantClient, faqs: List[Dict[str, str]]) -> None:
|
||
points = []
|
||
for idx, faq in enumerate(faqs):
|
||
vector = get_embedding(faq["question"])
|
||
point = qdrant_models.PointStruct(
|
||
id=idx,
|
||
vector=vector,
|
||
payload={"question": faq["question"], "answer": faq["answer"]}
|
||
)
|
||
points.append(point)
|
||
client.upsert(collection_name=COLLECTION_NAME, points=points)
|
||
```
|
||
|
||
*src/main.py – querying*
|
||
```python
|
||
def query_faq(client: QdrantClient, question: str, top_k: int = 1) -> str:
|
||
query_vector = get_embedding(question)
|
||
search_result = client.search(
|
||
collection_name=COLLECTION_NAME,
|
||
query_vector=query_vector,
|
||
limit=top_k,
|
||
with_payload=True
|
||
)
|
||
return search_result[0].payload.get("answer", "Answer not found.") if search_result else "Sorry, I couldn't find an answer to your question."
|
||
```
|
||
|
||
**Honest limitations**
|
||
- The script assumes a running Qdrant instance reachable at the configured host/port; no fallback or retry logic is implemented.
|
||
- Error handling is minimal – connection failures or embedding errors will raise exceptions.
|
||
- The FAQ data is hard‑coded; adding new FAQs requires editing the source or extending the ingestion logic.
|
||
|
||
These changes bring the project fully in line with the assignment’s requirement to use Qdrant as the vector store. |