from Serper.dev.
@@ -82,3 +84,66 @@ export function SerperDotDevOptions({ settings }) {
>
);
}
+
+export function BingSearchOptions({ settings }) {
+ return (
+ <>
+
+ You can get a Bing Web Search API subscription key{" "}
+
+ from the Azure portal.
+
+
+
+
+ To set up a Bing Web Search API subscription:
+
+
+ -
+ Go to the Azure portal:{" "}
+
+ https://portal.azure.com/
+
+
+ - Create a new Azure account or sign in with an existing one.
+ -
+ Navigate to the "Create a resource" section and search for "Bing
+ Search v7".
+
+ -
+ Select the "Bing Search v7" resource and create a new subscription.
+
+ -
+ Choose the pricing tier that suits your needs (free tier available).
+
+ - Obtain the API key for your Bing Web Search subscription.
+
+ >
+ );
+}
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/icons/bing.png b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/icons/bing.png
new file mode 100644
index 00000000..bfe1c836
Binary files /dev/null and b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/icons/bing.png differ
diff --git a/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/index.jsx b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/index.jsx
index 0581983f..8e8f054e 100644
--- a/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/index.jsx
+++ b/frontend/src/pages/WorkspaceSettings/AgentConfig/WebSearchSelection/index.jsx
@@ -2,11 +2,13 @@ import React, { useEffect, useRef, useState } from "react";
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 { CaretUpDown, MagnifyingGlass, X } from "@phosphor-icons/react";
import SearchProviderItem from "./SearchProviderItem";
import {
SerperDotDevOptions,
GoogleSearchOptions,
+ BingSearchOptions,
} from "./SearchProviderOptions";
const SEARCH_PROVIDERS = [
@@ -34,6 +36,14 @@ const SEARCH_PROVIDERS = [
description:
"Serper.dev web-search. Free account with a 2,500 calls, but then paid.",
},
+ {
+ name: "Bing Search",
+ value: "bing-search",
+ logo: BingSearchIcon,
+ options: (settings) => ,
+ description:
+ "Web search powered by the Bing Search API. Free for 1000 queries per month.",
+ },
];
export default function AgentWebSearchSelection({
diff --git a/server/.env.example b/server/.env.example
index e38250be..f51d6177 100644
--- a/server/.env.example
+++ b/server/.env.example
@@ -228,4 +228,7 @@ TTS_PROVIDER="native"
# AGENT_GSE_CTX=
#------ Serper.dev ----------- https://serper.dev/
-# AGENT_SERPER_DEV_KEY=
\ No newline at end of file
+# AGENT_SERPER_DEV_KEY=
+
+#------ Bing Search ----------- https://portal.azure.com/
+# AGENT_BING_SEARCH_API_KEY=
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index 52393a02..ac052319 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -70,7 +70,11 @@ const SystemSettings = {
agent_search_provider: (update) => {
try {
if (update === "none") return null;
- if (!["google-search-engine", "serper-dot-dev"].includes(update))
+ if (
+ !["google-search-engine", "serper-dot-dev", "bing-search"].includes(
+ update
+ )
+ )
throw new Error("Invalid SERP provider.");
return String(update);
} catch (e) {
@@ -171,6 +175,7 @@ const SystemSettings = {
AgentGoogleSearchEngineId: process.env.AGENT_GSE_CTX || null,
AgentGoogleSearchEngineKey: process.env.AGENT_GSE_KEY || null,
AgentSerperApiKey: process.env.AGENT_SERPER_DEV_KEY || null,
+ AgentBingSearchApiKey: process.env.AGENT_BING_SEARCH_API_KEY || null,
};
},
diff --git a/server/utils/agents/aibitat/plugins/web-browsing.js b/server/utils/agents/aibitat/plugins/web-browsing.js
index 198b3ec5..b30688f1 100644
--- a/server/utils/agents/aibitat/plugins/web-browsing.js
+++ b/server/utils/agents/aibitat/plugins/web-browsing.js
@@ -65,6 +65,9 @@ const webBrowsing = {
case "serper-dot-dev":
engine = "_serperDotDev";
break;
+ case "bing-search":
+ engine = "_bingWebSearch";
+ break;
default:
engine = "_googleSearchEngine";
}
@@ -172,6 +175,49 @@ const webBrowsing = {
return `No information was found online for the search query.`;
return JSON.stringify(data);
},
+ _bingWebSearch: async function (query) {
+ if (!process.env.AGENT_BING_SEARCH_API_KEY) {
+ this.super.introspect(
+ `${this.caller}: I can't use Bing Web Search because the user has not defined the required API key.\nVisit: https://portal.azure.com/ to create the API key.`
+ );
+ return `Search is disabled and no content was found. This functionality is disabled because the user has not set it up yet.`;
+ }
+
+ const searchURL = new URL(
+ "https://api.bing.microsoft.com/v7.0/search"
+ );
+ searchURL.searchParams.append("q", query);
+
+ this.super.introspect(
+ `${this.caller}: Using Bing Web Search to search for "${
+ query.length > 100 ? `${query.slice(0, 100)}...` : query
+ }"`
+ );
+
+ const searchResponse = await fetch(searchURL, {
+ headers: {
+ "Ocp-Apim-Subscription-Key":
+ process.env.AGENT_BING_SEARCH_API_KEY,
+ },
+ })
+ .then((res) => res.json())
+ .then((data) => {
+ const searchResults = data.webPages?.value || [];
+ return searchResults.map((result) => ({
+ title: result.name,
+ link: result.url,
+ snippet: result.snippet,
+ }));
+ })
+ .catch((e) => {
+ console.log(e);
+ return [];
+ });
+
+ if (searchResponse.length === 0)
+ return `No information was found online for the search query.`;
+ return JSON.stringify(searchResponse);
+ },
});
},
};
diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js
index c95ccd57..d6900ae5 100644
--- a/server/utils/helpers/updateENV.js
+++ b/server/utils/helpers/updateENV.js
@@ -399,6 +399,10 @@ const KEY_MAPPING = {
envKey: "AGENT_SERPER_DEV_KEY",
checks: [],
},
+ AgentBingSearchApiKey: {
+ envKey: "AGENT_BING_SEARCH_API_KEY",
+ checks: [],
+ },
// TTS/STT Integration ENVS
TextToSpeechProvider: {
@@ -762,6 +766,7 @@ async function dumpENV() {
"AGENT_GSE_CTX",
"AGENT_GSE_KEY",
"AGENT_SERPER_DEV_KEY",
+ "AGENT_BING_SEARCH_API_KEY",
];
// Simple sanitization of each value to prevent ENV injection via newline or quote escaping.