feat: solution for 'Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily)'

This commit is contained in:
2026-07-01 14:30:48 +03:00
parent c11f8de6a7
commit d8ce6c3861
5 changed files with 274 additions and 132 deletions
+123
View File
@@ -0,0 +1,123 @@
const fetch = require('node-fetch');
class QdrantClient {
/**
* Create a new Qdrant client.
* @param {Object} options
* @param {string} [options.url] - Qdrant service URL. Can also be set via QDRANT_URL env variable.
* @param {string} [options.apiKey] - API key for authentication. Can also be set via QDRANT_API_KEY env variable.
*/
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}`;
}
}
/**
* Internal helper to perform HTTP requests to Qdrant.
* @param {string} path - API path (e.g., '/collections')
* @param {string} method - HTTP method
* @param {Object|null} body - Request payload
* @returns {Promise<Object>} - Parsed JSON response
*/
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);
}
try {
const res = await fetch(fullUrl, options);
if (!res.ok) {
const errText = await res.text();
throw new Error(
`Qdrant request failed: ${res.status} ${res.statusText} - ${errText}`
);
}
return await res.json();
} catch (err) {
console.error(`Error during Qdrant request to ${path}:`, err);
throw err;
}
}
/**
* Create a new collection.
* @param {string} name - Collection name
* @param {Object} vectorsConfig - Configuration for vectors (e.g., { size: 1536, distance: 'Cosine' })
* @returns {Promise<Object>}
*/
async createCollection(name, vectorsConfig) {
const body = {
vectors: vectorsConfig,
};
return await this.request(`/collections/${name}`, 'PUT', body);
}
/**
* Delete an existing collection.
* @param {string} name - Collection name
* @returns {Promise<Object>}
*/
async deleteCollection(name) {
return await this.request(`/collections/${name}`, 'DELETE');
}
/**
* Upsert points into a collection.
* @param {string} collectionName - Target collection
* @param {Array<Object>} points - Array of point objects (id, vector, payload)
* @returns {Promise<Object>}
*/
async upsertPoints(collectionName, points) {
const body = {
points,
};
return await this.request(
`/collections/${collectionName}/points`,
'PUT',
body
);
}
/**
* Search points in a collection.
* @param {string} collectionName - Target collection
* @param {Array<number>} vector - Query vector
* @param {number} [limit=10] - Number of results
* @param {Object} [params={}] - Optional search parameters
* @returns {Promise<Object>}
*/
async searchPoints(collectionName, vector, limit = 10, params = {}) {
const body = {
vector,
limit,
params,
};
return await this.request(
`/collections/${collectionName}/points/search`,
'POST',
body
);
}
}
module.exports = QdrantClient;