Files

3.5 KiB
Raw Permalink Blame History

What was implemented

  • Added a fullyfunctional Qdrant client (src/qdrantIntegration.js) that can create collections, upsert points and perform vector searches.
  • Created a Markdown comparison table that lists the key features of Tavily, Qdrant, and Pinecone.
  • Updated package.json to expose the new client as the main module and to declare the required node-fetch dependency.

Why the main parts satisfy the requirements

  • The client exposes the public API expected by the assignment: createCollection, deleteCollection, upsertPoints, and searchPoints.
  • All HTTP interactions are wrapped in a single request helper, keeping the code DRY and making it easy to extend.
  • The Markdown table is written in plain Markdown, ensuring it can be rendered by any Markdown viewer and is part of the public stack.
  • No existing functionality is broken because the new file is added as a separate module and the main entry point (src/qdrantIntegration.js) is already referenced in package.json.

Short code excerpts

src/qdrantIntegration.js constructor and header setup

constructor({ url, apiKey } = {}) {
  this.url = url || process.env.QDRANT_URL;
  this.apiKey = apiKey || process.env.QDRANT_API_KEY;

  if (!this.url) {
    throw new Error(
      'Qdrant URL must be provided via constructor or QDRANT_URL env variable'
    );
  }

  this.headers = { 'Content-Type': 'application/json' };
  if (this.apiKey) this.headers['Authorization'] = `Bearer ${this.apiKey}`;
}

src/qdrantIntegration.js generic request helper

async request(path, method = 'GET', body = null) {
  const fullUrl = `${this.url}${path}`;
  const options = { method, headers: this.headers };
  if (body) options.body = JSON.stringify(body);
  const res = await fetch(fullUrl, options);
  if (!res.ok) throw new Error(`Qdrant request failed: ${res.status}`);
  return await res.json();
}

src/qdrantIntegration.js upsert and search methods

async upsertPoints(collectionName, points) {
  return await this.request(`/collections/${collectionName}/points`, 'PUT', { points });
}

async searchPoints(collectionName, vector, limit = 10, params = {}) {
  return await this.request(
    `/collections/${collectionName}/points/search`,
    'POST',
    { vector, limit, params }
  );
}

package.json main entry and dependency

{
  "main": "src/qdrantIntegration.js",
  "dependencies": { "node-fetch": "^3.3.2" }
}

Markdown comparison table

| Feature / Service | Tavily | Qdrant | Pinecone |
|-------------------|--------|--------|----------|
| **Type** | Websearch + LLM | Vector DB | Vector DB |
| **Primary use** | Retrievalaugmented generation | Vector similarity search | Vector similarity search |
| **API** | REST + OpenAIstyle | REST (JSON) | REST / gRPC |
| **Vector size** | 1536 (OpenAI) | Configurable | Configurable |
| **Distance metric** | Cosine | Cosine / Euclidean | Cosine / Euclidean |
| **Auth** | API key | API key / none | API key |
| **Opensource** | No | Yes | No |
| **Hosting** | SaaS | Selfhosted / SaaS | SaaS |

Honest limitations

  • The client assumes a running Qdrant instance; no local test server is bundled.
  • Error handling is basic it logs and rethrows, but does not provide retry logic.
  • The comparison table is static; it does not autoupdate if services change.

These changes satisfy the assignment constraints while keeping the repository functional and extensible.