diff --git a/docker/.env.example b/docker/.env.example
index 174a9d69272..a38b4c5a293 100644
--- a/docker/.env.example
+++ b/docker/.env.example
@@ -241,4 +241,7 @@ GID='1000'
# AGENT_SERPER_DEV_KEY=
#------ Bing Search ----------- https://portal.azure.com/
-# AGENT_BING_SEARCH_API_KEY=
\ No newline at end of file
+# AGENT_BING_SEARCH_API_KEY=
+
+#------ Serply.io ----------- https://serply.io/
+# AGENT_SERPLY_API_KEY=
diff --git a/docker/HOW_TO_USE_DOCKER.md b/docker/HOW_TO_USE_DOCKER.md
index fed16a2747e..f570dce900c 100644
--- a/docker/HOW_TO_USE_DOCKER.md
+++ b/docker/HOW_TO_USE_DOCKER.md
@@ -89,7 +89,6 @@ mintplexlabs/anythingllm;
| Docker Compose |
-
version: '3.8'
services:
anythingllm:
@@ -116,6 +115,7 @@ mintplexlabs/anythingllm;
- TTS_PROVIDER=native
- PASSWORDMINCHAR=8
- AGENT_SERPER_DEV_KEY="SERPER DEV API KEY"
+ - AGENT_SERPLY_API_KEY="Serply.io API KEY"
volumes:
- anythingllm_storage:/app/server/storage
restart: always
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/SearchProviderOptions/index.jsx b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/SearchProviderOptions/index.jsx
index 3d579ed43ae..58ceb844741 100644
--- a/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/SearchProviderOptions/index.jsx
+++ b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/SearchProviderOptions/index.jsx
@@ -147,3 +147,38 @@ export function BingSearchOptions({ settings }) {
>
);
}
+
+export function SerplySearchOptions({ settings }) {
+ return (
+ <>
+
+ You can get a free API key{" "}
+
+ from Serply.io.
+
+
+
+ >
+ );
+}
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/icons/serply.png b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/icons/serply.png
new file mode 100644
index 00000000000..8ac0ef7c00d
Binary files /dev/null and b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/icons/serply.png differ
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/index.jsx b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/index.jsx
index 8e8f054ea08..0bbc053ab83 100644
--- a/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/index.jsx
+++ b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/index.jsx
@@ -3,12 +3,14 @@ import AnythingLLMIcon from "@/media/logo/anything-llm-icon.png";
import GoogleSearchIcon from "./icons/google.png";
import SerperDotDevIcon from "./icons/serper.png";
import BingSearchIcon from "./icons/bing.png";
+import SerplySearchIcon from "./icons/serply.png"
import { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react";
import SearchProviderItem from "./SearchProviderItem";
import {
SerperDotDevOptions,
GoogleSearchOptions,
BingSearchOptions,
+ SerplySearchOptions
} from "./SearchProviderOptions";
const SEARCH_PROVIDERS = [
@@ -44,6 +46,14 @@ const SEARCH_PROVIDERS = [
description:
"Web search powered by the Bing Search API. Free for 1000 queries per month.",
},
+ {
+ name: "Serply.io",
+ value: "serply-engine",
+ logo: SerplySearchIcon,
+ options: (settings) => ,
+ description:
+ "Serply.io web-search. Free account with a 100 calls/month forever.",
+ },
];
export default function AgentWebSearchSelection({
diff --git a/server/.env.example b/server/.env.example
index 6148d594f92..a88a8a039b0 100644
--- a/server/.env.example
+++ b/server/.env.example
@@ -238,3 +238,6 @@ TTS_PROVIDER="native"
#------ Bing Search ----------- https://portal.azure.com/
# AGENT_BING_SEARCH_API_KEY=
+
+#------ Serply.io ----------- https://serply.io/
+# AGENT_SERPLY_API_KEY=
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index ac052319847..3cb0456f429 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -71,7 +71,7 @@ const SystemSettings = {
try {
if (update === "none") return null;
if (
- !["google-search-engine", "serper-dot-dev", "bing-search"].includes(
+ !["google-search-engine", "serper-dot-dev", "bing-search", "serply-engine"].includes(
update
)
)
@@ -176,6 +176,7 @@ const SystemSettings = {
AgentGoogleSearchEngineKey: process.env.AGENT_GSE_KEY || null,
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 b30688f1749..00b004cbc4b 100644
--- a/server/utils/agents/aibitat/plugins/web-browsing.js
+++ b/server/utils/agents/aibitat/plugins/web-browsing.js
@@ -68,6 +68,9 @@ const webBrowsing = {
case "bing-search":
engine = "_bingWebSearch";
break;
+ case "serply-engine":
+ engine = "_serplyEngine";
+ break;
default:
engine = "_googleSearchEngine";
}
@@ -218,6 +221,72 @@ const webBrowsing = {
return `No information was found online for the search query.`;
return JSON.stringify(searchResponse);
},
+ _serplyEngine: async function (query, language = "en", hl = "us", limit = 100, device_type = "desktop", proxy_location = "US") {
+ // query (str): The query to search for
+ // hl (str): Host Language code to display results in (reference https://developers.google.com/custom-search/docs/xml_results?hl=en#wsInterfaceLanguages)
+ // limit (int): The maximum number of results to return [10-100, defaults to 100]
+ // device_type: get results based on desktop/mobile (defaults to desktop)
+
+ if (!process.env.AGENT_SERPLY_API_KEY) {
+ this.super.introspect(
+ `${this.caller}: I can't use Serply.io searching because the user has not defined the required API key.\nVisit: https://serply.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 Serply to search for "${
+ query.length > 100 ? `${query.slice(0, 100)}...` : query
+ }"`
+ );
+
+ const params = new URLSearchParams({
+ q: query,
+ language: language,
+ hl,
+ gl: proxy_location.toUpperCase()
+ })
+ const url = `https://api.serply.io/v1/search/${params.toString()}`
+ const { response, error } = await fetch(
+ url,
+ {
+ method: "GET",
+ headers: {
+ "X-API-KEY": process.env.AGENT_SERPLY_API_KEY,
+ "Content-Type": "application/json",
+ "User-Agent": "anything-llm",
+ "X-Proxy-Location": proxy_location,
+ "X-User-Agent": device_type
+ }
+ }
+ )
+ .then((res) => res.json())
+ .then((data) => {
+ if (data?.message === "Unauthorized"){
+ return { response: null, error: "Unauthorized. Please double check your AGENT_SERPLY_API_KEY" };
+ }
+ 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 = [];
+ response.results?.forEach((searchResult) => {
+ const { title, link, description } = searchResult;
+ data.push({
+ title,
+ link,
+ snippet: description,
+ });
+ });
+
+ if (data.length === 0)
+ return `No information was found online for the search query.`;
+ return JSON.stringify(data);
+ },
});
},
};
diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js
index 1a0e710a975..3f2baf7e3ef 100644
--- a/server/utils/helpers/updateENV.js
+++ b/server/utils/helpers/updateENV.js
@@ -403,6 +403,10 @@ const KEY_MAPPING = {
envKey: "AGENT_BING_SEARCH_API_KEY",
checks: [],
},
+ AgentSerplyApiKey: {
+ envKey: "AGENT_SERPLY_API_KEY",
+ checks: [],
+ },
// TTS/STT Integration ENVS
TextToSpeechProvider: {
@@ -769,6 +773,7 @@ async function dumpENV() {
"AGENT_GSE_KEY",
"AGENT_SERPER_DEV_KEY",
"AGENT_BING_SEARCH_API_KEY",
+ "AGENT_SERPLY_API_KEY"
];
// Simple sanitization of each value to prevent ENV injection via newline or quote escaping.
|