diff --git a/.vscode/settings.json b/.vscode/settings.json
index 549fd1574..4769a939c 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -41,6 +41,7 @@
"Qdrant",
"royalblue",
"searxng",
+ "SearchApi",
"Serper",
"Serply",
"streamable",
diff --git a/docker/.env.example b/docker/.env.example
index 56be87cb4..1521a307a 100644
--- a/docker/.env.example
+++ b/docker/.env.example
@@ -252,6 +252,10 @@ GID='1000'
# AGENT_GSE_KEY=
# AGENT_GSE_CTX=
+#------ SearchApi.io ----------- https://www.searchapi.io/
+# AGENT_SEARCHAPI_API_KEY=
+# AGENT_SEARCHAPI_ENGINE=google
+
#------ Serper.dev ----------- https://serper.dev/
# AGENT_SERPER_DEV_KEY=
diff --git a/docker/HOW_TO_USE_DOCKER.md b/docker/HOW_TO_USE_DOCKER.md
index 1e95bd8a0..2eeaee060 100644
--- a/docker/HOW_TO_USE_DOCKER.md
+++ b/docker/HOW_TO_USE_DOCKER.md
@@ -117,8 +117,8 @@ services:
- WHISPER_PROVIDER=local
- TTS_PROVIDER=native
- PASSWORDMINCHAR=8
- - AGENT_SERPER_DEV_KEY="SERPER DEV API KEY"
- - AGENT_SERPLY_API_KEY="Serply.io API KEY"
+ # Add any other keys here for services or settings
+ # you can find in the docker/.env.example file
volumes:
- anythingllm_storage:/app/server/storage
restart: always
diff --git a/frontend/src/pages/Admin/Agents/WebSearchSelection/SearchProviderOptions/index.jsx b/frontend/src/pages/Admin/Agents/WebSearchSelection/SearchProviderOptions/index.jsx
index f7ad09c03..1e5349857 100644
--- a/frontend/src/pages/Admin/Agents/WebSearchSelection/SearchProviderOptions/index.jsx
+++ b/frontend/src/pages/Admin/Agents/WebSearchSelection/SearchProviderOptions/index.jsx
@@ -50,6 +50,83 @@ export function GoogleSearchOptions({ settings }) {
);
}
+const SearchApiEngines = [
+ { name: "Google Search", value: "google" },
+ { name: "Google Maps", value: "google_maps" },
+ { name: "Google Shopping", value: "google_shopping" },
+ { name: "Google News", value: "google_news" },
+ { name: "Google Jobs", value: "google_jobs" },
+ { name: "Google Scholar", value: "google_scholar" },
+ { name: "Google Finance", value: "google_finance" },
+ { name: "Google Patents", value: "google_patents" },
+ { name: "YouTube", value: "youtube" },
+ { name: "Bing", value: "bing" },
+ { name: "Bing News", value: "bing_news" },
+ { name: "Amazon Product Search", value: "amazon_search" },
+ { name: "Baidu", value: "baidu" },
+];
+export function SearchApiOptions({ settings }) {
+ return (
+ <>
+
+ You can get a free API key{" "}
+
+ from SearchApi.
+
+
+
+ >
+ );
+}
+
export function SerperDotDevOptions({ settings }) {
return (
<>
diff --git a/frontend/src/pages/Admin/Agents/WebSearchSelection/icons/searchapi.png b/frontend/src/pages/Admin/Agents/WebSearchSelection/icons/searchapi.png
new file mode 100644
index 000000000..65bae79bf
Binary files /dev/null and b/frontend/src/pages/Admin/Agents/WebSearchSelection/icons/searchapi.png differ
diff --git a/frontend/src/pages/Admin/Agents/WebSearchSelection/index.jsx b/frontend/src/pages/Admin/Agents/WebSearchSelection/index.jsx
index c1f14cc6a..fd201fb90 100644
--- a/frontend/src/pages/Admin/Agents/WebSearchSelection/index.jsx
+++ b/frontend/src/pages/Admin/Agents/WebSearchSelection/index.jsx
@@ -1,6 +1,7 @@
import React, { useEffect, useRef, useState } from "react";
import AnythingLLMIcon from "@/media/logo/anything-llm-icon.png";
import GoogleSearchIcon from "./icons/google.png";
+import SearchApiIcon from "./icons/searchapi.png";
import SerperDotDevIcon from "./icons/serper.png";
import BingSearchIcon from "./icons/bing.png";
import SerplySearchIcon from "./icons/serply.png";
@@ -14,6 +15,7 @@ import {
import SearchProviderItem from "./SearchProviderItem";
import WebSearchImage from "@/media/agents/scrape-websites.png";
import {
+ SearchApiOptions,
SerperDotDevOptions,
GoogleSearchOptions,
BingSearchOptions,
@@ -38,6 +40,14 @@ const SEARCH_PROVIDERS = [
description:
"Web search powered by a custom Google Search Engine. Free for 100 queries per day.",
},
+ {
+ name: "SearchApi",
+ value: "searchapi",
+ logo: SearchApiIcon,
+ options: (settings) => ,
+ description:
+ "SearchApi delivers structured data from multiple search engines. Free for 100 queries, but then paid. ",
+ },
{
name: "Serper.dev",
value: "serper-dot-dev",
diff --git a/server/.env.example b/server/.env.example
index 22bd557ee..f942d6832 100644
--- a/server/.env.example
+++ b/server/.env.example
@@ -241,6 +241,10 @@ TTS_PROVIDER="native"
# AGENT_GSE_KEY=
# AGENT_GSE_CTX=
+#------ SearchApi.io ----------- https://www.searchapi.io/
+# AGENT_SEARCHAPI_API_KEY=
+# AGENT_SEARCHAPI_ENGINE=google
+
#------ Serper.dev ----------- https://serper.dev/
# AGENT_SERPER_DEV_KEY=
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index b85f3cb8c..e9ae3f3e9 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -81,6 +81,7 @@ const SystemSettings = {
if (
![
"google-search-engine",
+ "searchapi",
"serper-dot-dev",
"bing-search",
"serply-engine",
@@ -218,6 +219,8 @@ const SystemSettings = {
// --------------------------------------------------------
AgentGoogleSearchEngineId: process.env.AGENT_GSE_CTX || null,
AgentGoogleSearchEngineKey: !!process.env.AGENT_GSE_KEY || null,
+ AgentSearchApiKey: !!process.env.AGENT_SEARCHAPI_API_KEY || null,
+ AgentSearchApiEngine: process.env.AGENT_SEARCHAPI_ENGINE || "google",
AgentSerperApiKey: !!process.env.AGENT_SERPER_DEV_KEY || null,
AgentBingSearchApiKey: !!process.env.AGENT_BING_SEARCH_API_KEY || null,
AgentSerplyApiKey: !!process.env.AGENT_SERPLY_API_KEY || null,
diff --git a/server/utils/agents/aibitat/plugins/web-browsing.js b/server/utils/agents/aibitat/plugins/web-browsing.js
index f4269fe13..76849056e 100644
--- a/server/utils/agents/aibitat/plugins/web-browsing.js
+++ b/server/utils/agents/aibitat/plugins/web-browsing.js
@@ -62,6 +62,9 @@ const webBrowsing = {
case "google-search-engine":
engine = "_googleSearchEngine";
break;
+ case "searchapi":
+ engine = "_searchApi";
+ break;
case "serper-dot-dev":
engine = "_serperDotDev";
break;
@@ -130,6 +133,72 @@ const webBrowsing = {
return JSON.stringify(data);
},
+ /**
+ * Use SearchApi
+ * SearchApi supports multiple search engines like Google Search, Bing Search, Baidu Search, Google News, YouTube, and many more.
+ * https://www.searchapi.io/
+ */
+ _searchApi: async function (query) {
+ if (!process.env.AGENT_SEARCHAPI_API_KEY) {
+ this.super.introspect(
+ `${this.caller}: I can't use SearchApi searching because the user has not defined the required API key.\nVisit: https://www.searchapi.io/ to create the API key for free.`
+ );
+ return `Search is disabled and no content was found. This functionality is disabled because the user has not set it up yet.`;
+ }
+
+ this.super.introspect(
+ `${this.caller}: Using SearchApi to search for "${
+ query.length > 100 ? `${query.slice(0, 100)}...` : query
+ }"`
+ );
+
+ const engine = process.env.AGENT_SEARCHAPI_ENGINE;
+ const params = new URLSearchParams({
+ engine: engine,
+ q: query,
+ });
+
+ const url = `https://www.searchapi.io/api/v1/search?${params.toString()}`;
+ const { response, error } = await fetch(url, {
+ method: "GET",
+ headers: {
+ Authorization: `Bearer ${process.env.AGENT_SEARCHAPI_API_KEY}`,
+ "Content-Type": "application/json",
+ "X-SearchApi-Source": "AnythingLLM",
+ },
+ })
+ .then((res) => res.json())
+ .then((data) => {
+ return { response: data, error: null };
+ })
+ .catch((e) => {
+ return { response: null, error: e.message };
+ });
+ if (error)
+ return `There was an error searching for content. ${error}`;
+
+ const data = [];
+ if (response.hasOwnProperty("knowledge_graph"))
+ data.push(response.knowledge_graph?.description);
+ if (response.hasOwnProperty("answer_box"))
+ data.push(response.answer_box?.answer);
+ response.organic_results?.forEach((searchResult) => {
+ const { title, link, snippet } = searchResult;
+ data.push({
+ title,
+ link,
+ snippet,
+ });
+ });
+
+ if (data.length === 0)
+ return `No information was found online for the search query.`;
+ this.super.introspect(
+ `${this.caller}: I found ${data.length} results - looking over them now.`
+ );
+ return JSON.stringify(data);
+ },
+
/**
* Use Serper.dev
* Free to set up, easy to use, 2,500 calls for free one-time
diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js
index c579da188..af5a460db 100644
--- a/server/utils/helpers/updateENV.js
+++ b/server/utils/helpers/updateENV.js
@@ -435,6 +435,14 @@ const KEY_MAPPING = {
envKey: "AGENT_GSE_KEY",
checks: [],
},
+ AgentSearchApiKey: {
+ envKey: "AGENT_SEARCHAPI_API_KEY",
+ checks: [],
+ },
+ AgentSearchApiEngine: {
+ envKey: "AGENT_SEARCHAPI_ENGINE",
+ checks: [],
+ },
AgentSerperApiKey: {
envKey: "AGENT_SERPER_DEV_KEY",
checks: [],