Files
povtornyy-ekzamen-faq-bot-c…/SOLUTION.md
T

2.9 KiB
Raw Blame History

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 FAQbot behaviour.

Short code excerpts

src/main.py Qdrant client initialization

client = QdrantClient(
    host=QDRANT_HOST,
    port=QDRANT_PORT,
    api_key=QDRANT_API_KEY
)

src/main.py collection creation

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

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

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 hardcoded; adding new FAQs requires editing the source or extending the ingestion logic.

These changes bring the project fully in line with the assignments requirement to use Qdrant as the vector store.