From b842ffbc733f228a64645125cffb0ad504ab1ffa Mon Sep 17 00:00:00 2001 From: Tavily PR Agent Date: Tue, 14 Jul 2026 13:36:07 +0000 Subject: [PATCH] feat: add Tavily as configurable search provider option --- .env.example | 2 ++ app/config.tsx | 2 +- app/tools/searchProviders.tsx | 19 +++++++++++++++++++ package.json | 1 + 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 514b9dd..1e955a2 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,8 @@ OPENAI_API_KEY=APIKEYGOESHERE SERPER_API=APIKEYGOESHERE # Brave Search API Key (Serper is the default, brave is an alternative option for search) BRAVE_SEARCH_API_KEY=APIKEYGOESHERE +# OPTIONAL - Tavily Search API Key (alternative search provider) +TAVILY_API_KEY=APIKEYGOESHERE # OPTIONAL - Set LAN GPU server, examples: diff --git a/app/config.tsx b/app/config.tsx index 05fd639..e094e5a 100644 --- a/app/config.tsx +++ b/app/config.tsx @@ -7,7 +7,7 @@ export const config = { useOllamaInference: false, useOllamaEmbeddings: false, - searchProvider: 'serper', // 'serper', 'google' // 'serper' is the default + searchProvider: 'serper', // 'serper', 'google', 'brave', 'tavily' // 'serper' is the default inferenceModel: 'llama-3.1-70b-versatile', // Groq: 'mixtral-8x7b-32768', 'gemma-7b-it' // OpenAI: 'gpt-3.5-turbo', 'gpt-4' // Ollama 'mistral', 'llama3' etc inferenceAPIKey: process.env.GROQ_API_KEY, // Groq: process.env.GROQ_API_KEY // OpenAI: process.env.OPENAI_API_KEY // Ollama: 'ollama' is the default embeddingsModel: 'text-embedding-3-small', // Ollama: 'llama2', 'nomic-embed-text' // OpenAI 'text-embedding-3-small', 'text-embedding-3-large' diff --git a/app/tools/searchProviders.tsx b/app/tools/searchProviders.tsx index 5eaab8c..d6f1787 100644 --- a/app/tools/searchProviders.tsx +++ b/app/tools/searchProviders.tsx @@ -1,6 +1,7 @@ "use server"; import { SearchResult } from '@/components/answer/SearchResultsComponent'; import { config } from '../config'; +import { tavily } from '@tavily/core'; export async function getSearchResults(userMessage: string): Promise { switch (config.searchProvider) { @@ -10,6 +11,8 @@ export async function getSearchResults(userMessage: string): Promise { return serperSearch(userMessage); case "google": return googleSearch(userMessage); + case "tavily": + return tavilySearch(userMessage); default: return Promise.reject(new Error(`Unsupported search provider: ${config.searchProvider}`)); } @@ -100,6 +103,22 @@ export async function serperSearch(message: string, numberOfPagesToScan = config } } +export async function tavilySearch(message: string, numberOfPagesToScan = config.numberOfPagesToScan): Promise { + try { + const tvly = tavily({ apiKey: process.env.TAVILY_API_KEY as string }); + const response = await tvly.search(message, { maxResults: numberOfPagesToScan }); + const final = response.results.map((result: any): SearchResult => ({ + title: result.title, + link: result.url, + favicon: `https://www.google.com/s2/favicons?domain=${new URL(result.url).hostname}&sz=128` + })); + return final; + } catch (error) { + console.error('Error fetching search results:', error); + throw error; + } +} + export async function getImages(message: string): Promise<{ title: string; link: string }[]> { const url = 'https://google.serper.dev/images'; const data = JSON.stringify({ diff --git a/package.json b/package.json index 05dedf0..48c0e98 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@langchain/community": "latest", "@langchain/openai": "^0.0.25", "@phosphor-icons/react": "^2.1.5", + "@tavily/core": "^0.6.1", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.0.2",