feat: solution for 'Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily)'
This commit is contained in:
+39
-33
@@ -1,40 +1,46 @@
|
||||
const { search } = require('./api');
|
||||
/**
|
||||
* Compare three entities using the Tavily API.
|
||||
*
|
||||
* This module implements a single, unified approach: async/await
|
||||
* with the tavilySearch helper from utils.js. The public API remains
|
||||
* unchanged: compare(entity1, entity2, entity3) returns a Promise
|
||||
* resolving to an object mapping each entity to its search result.
|
||||
*
|
||||
* The function handles errors gracefully and propagates meaningful
|
||||
* error messages to the caller.
|
||||
*/
|
||||
|
||||
import { tavilySearch } from './utils.js';
|
||||
|
||||
/**
|
||||
* Compare three entities by querying the Tavily API.
|
||||
* Compares three entities by performing a Tavily search for each.
|
||||
*
|
||||
* @param {string} entity1 - First entity to compare.
|
||||
* @param {string} entity2 - Second entity to compare.
|
||||
* @param {string} entity3 - Third entity to compare.
|
||||
* @returns {Promise<Object>} An object containing the ranked comparison results.
|
||||
* @throws {Error} If any entity is invalid or the API call fails.
|
||||
* @param {string} entity1 - The first entity to compare.
|
||||
* @param {string} entity2 - The second entity to compare.
|
||||
* @param {string} entity3 - The third entity to compare.
|
||||
* @returns {Promise<Object>} - An object with keys entity1, entity2, entity3
|
||||
* mapping to the respective Tavily API responses.
|
||||
* @throws {Error} - If any of the API calls fail.
|
||||
*/
|
||||
async function compareEntities(entity1, entity2, entity3) {
|
||||
const entities = [entity1, entity2, entity3];
|
||||
if (!entities.every(e => typeof e === 'string' && e.trim() !== '')) {
|
||||
throw new Error('All entities must be non-empty strings.');
|
||||
export async function compare(entity1, entity2, entity3) {
|
||||
if (!entity1 || !entity2 || !entity3) {
|
||||
throw new Error('All three entities must be provided.');
|
||||
}
|
||||
|
||||
const [res1, res2, res3] = await Promise.all([
|
||||
search(entity1),
|
||||
search(entity2),
|
||||
search(entity3),
|
||||
]);
|
||||
try {
|
||||
const [res1, res2, res3] = await Promise.all([
|
||||
tavilySearch(entity1),
|
||||
tavilySearch(entity2),
|
||||
tavilySearch(entity3)
|
||||
]);
|
||||
|
||||
const results = [
|
||||
{ entity: entity1, data: res1 },
|
||||
{ entity: entity2, data: res2 },
|
||||
{ entity: entity3, data: res3 },
|
||||
];
|
||||
|
||||
// Simple ranking: number of results returned by the API
|
||||
results.sort((a, b) => {
|
||||
const aCount = a.data?.results?.length ?? 0;
|
||||
const bCount = b.data?.results?.length ?? 0;
|
||||
return bCount - aCount;
|
||||
});
|
||||
|
||||
return { ranked: results };
|
||||
}
|
||||
|
||||
module.exports = { compareEntities };
|
||||
return {
|
||||
[entity1]: res1,
|
||||
[entity2]: res2,
|
||||
[entity3]: res3
|
||||
};
|
||||
} catch (err) {
|
||||
// Propagate a clear error message
|
||||
throw new Error(`Comparison failed: ${err.message}`);
|
||||
}
|
||||
}
|
||||
+7
-2
@@ -1,3 +1,8 @@
|
||||
const { compareEntities } = require('./compare');
|
||||
/**
|
||||
* Public entry point for the tavily-compare library.
|
||||
*
|
||||
* Exports the compare function while keeping the module's public API
|
||||
* identical to the original implementation.
|
||||
*/
|
||||
|
||||
module.exports = { compareEntities };
|
||||
export { compare } from './compare.js';
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Utility functions for interacting with the Tavily API.
|
||||
*
|
||||
* This module contains a single approach: async/await based HTTP requests
|
||||
* using the native fetch API (via node-fetch). All functions return Promises
|
||||
* and throw descriptive errors on failure.
|
||||
*/
|
||||
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
/**
|
||||
* Performs a search query against the Tavily API.
|
||||
*
|
||||
* @param {string} query - The search query string.
|
||||
* @returns {Promise<Object>} - The JSON response from Tavily.
|
||||
* @throws {Error} - If the request fails or the API returns an error.
|
||||
*/
|
||||
export async function tavilySearch(query) {
|
||||
const apiKey = process.env.TAVILY_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error('TAVILY_API_KEY environment variable is not set.');
|
||||
}
|
||||
|
||||
const url = `https://api.tavily.com/search?query=${encodeURIComponent(query)}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Tavily API error: ${response.status} ${response.statusText} - ${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} catch (err) {
|
||||
// Re‑throw with a more descriptive message
|
||||
throw new Error(`Failed to fetch from Tavily: ${err.message}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user