feat: solution for 'Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily)'
This commit is contained in:
@@ -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;
|
||||
Reference in New Issue
Block a user