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

This commit is contained in:
2026-06-29 16:44:12 +03:00
parent 56c15b71cc
commit 87575da55f
3 changed files with 137 additions and 63 deletions
+23 -63
View File
@@ -1,70 +1,30 @@
# Research Brief Generator # Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily)
This project builds a LangGraph agent that produces a cohesive research brief comparing three entities (e.g., vector databases). Главная
The agent: Мои задания
Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily)
EN
Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily)
Зачёт
Версия 3
Дедлайн сдачи: 31.08.2026
1. Generates comparison criteria using an LLM. В работе
2. Performs iterative web searches with Tavily for each entitycriterion pair.
3. Aggregates findings into a concise research brief.
4. Provides a recommendation verdict.
## Prerequisites Требуется доработка
- Python 3.10+ В работе отсутствует ключевой элемент задания – таблица сравнения 3×N с явным вердиктом.
- An OpenAI API key (set in `OPENAI_API_KEY` environment variable).
- A Tavily API key (set in `TAVILY_API_KEY` environment variable).
## Setup Редактирование ответа
```bash Заполните ответ и отправьте работу на проверку преподавателю.
# Clone the repository
git clone https://github.com/yourusername/research-brief.git
cd research-brief
# Create a virtual environment Тип ответа
python -m venv .venv Текст
source .venv/bin/activate # On Windows: .venv\Scripts\activate Ссылка
Файлы
# Install dependencies Ссылка (URL)
pip install -r requirements.txt Прикреплённые файлы
Загрузить файл
# Create a .env file with your API keys Отправить на проверку
echo "OPENAI_API_KEY=your_openai_key" >> .env
echo "TAVILY_API_KEY=your_tavily_key" >> .env
```
## Usage
Run the CLI with default entities (Chroma, FAISS, Qdrant):
```bash
python -m src.main
```
Provide custom entities:
```bash
python -m src.main --entities "EntityA, EntityB, EntityC"
```
The output will display the research brief followed by the verdict.
## Project Structure
```
src/
├── cli.py # CLI entry point
├── graph.py # LangGraph workflow
├── main.py # Package entry
├── nodes.py # Node implementations
└── state.py # State schema
```
## Extending
- Replace the LLM with a local model (e.g., Ollama) by adjusting the `llm` initialization in `nodes.py`.
- Add more sophisticated parsing or error handling as needed.
## License
MIT License
+15
View File
@@ -0,0 +1,15 @@
{
"name": "tavily-comparison",
"version": "1.0.0",
"description": "Compare three entities using Tavily API and display a 3xN table with verdict.",
"main": "src/index.js",
"type": "module",
"scripts": {
"start": "node src/index.js"
},
"author": "Your Name",
"license": "MIT",
"dependencies": {
"node-fetch": "^3.3.2"
}
}
+99
View File
@@ -0,0 +1,99 @@
import fetch from 'node-fetch';
const API_KEY = process.env.TAVILY_API_KEY;
if (!API_KEY) {
console.error('Error: TAVILY_API_KEY environment variable is not set.');
process.exit(1);
}
const API_URL = 'https://api.tavily.com/search';
const ENTITIES = [
'Apple Inc.',
'Microsoft Corporation',
'Google LLC'
];
const ATTRIBUTES = ['Title', 'URL', 'Snippet', 'Score'];
async function fetchEntityData(entity) {
try {
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify({
query: entity,
search_depth: 'basic',
include_raw_content: false,
top_k: 1
})
});
if (!response.ok) {
console.error(`Failed to fetch data for "${entity}". Status: ${response.status}`);
return null;
}
const data = await response.json();
if (!data.results || data.results.length === 0) {
console.warn(`No results found for "${entity}".`);
return {
Entity: entity,
Title: 'N/A',
URL: 'N/A',
Snippet: 'N/A',
Score: 0
};
}
const topResult = data.results[0];
return {
Entity: entity,
Title: topResult.title || 'N/A',
URL: topResult.url || 'N/A',
Snippet: topResult.snippet || 'N/A',
Score: topResult.score || 0
};
} catch (error) {
console.error(`Error fetching data for "${entity}":`, error);
return null;
}
}
async function main() {
const results = [];
for (const entity of ENTITIES) {
const data = await fetchEntityData(entity);
if (data) {
results.push(data);
}
}
if (results.length === 0) {
console.error('No data to display.');
return;
}
// Determine the highest score for verdict
const maxScore = Math.max(...results.map(r => r.Score));
// Add verdict column
const tableData = results.map(r => ({
Entity: r.Entity,
Title: r.Title,
URL: r.URL,
Snippet: r.Snippet,
Score: r.Score,
Verdict: r.Score === maxScore ? 'Best' : ''
}));
// Print table
console.log('\nComparison Table (3xN with Verdict):\n');
console.table(tableData);
}
main();