From 680d38a3ce914537738b0b406e056045da2af7b6 Mon Sep 17 00:00:00 2001 From: jimmyzhuu Date: Thu, 23 Apr 2026 08:53:20 +0800 Subject: [PATCH] [FEAT] Add native Baidu Search provider for Agent web browsing (#5388) * feat: add native baidu search provider for agent web browsing * chore: address baidu search review feedback * refactor baiduSearch internal util to be locally scoped --------- Co-authored-by: Timothy Carambat --- docker/.env.example | 5 +- .../SearchProviderOptions/index.jsx | 37 ++++++ .../Agents/WebSearchSelection/icons/baidu.png | Bin 0 -> 40238 bytes .../Admin/Agents/WebSearchSelection/index.jsx | 10 ++ server/.env.example | 3 + server/models/systemSettings.js | 2 + .../agents/aibitat/plugins/web-browsing.js | 110 ++++++++++++++++++ server/utils/helpers/updateENV.js | 4 + 8 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 frontend/src/pages/Admin/Agents/WebSearchSelection/icons/baidu.png diff --git a/docker/.env.example b/docker/.env.example index 8efd57cb..9b73a290 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -378,6 +378,9 @@ GID='1000' #------ Bing Search ----------- https://portal.azure.com/ # AGENT_BING_SEARCH_API_KEY= +#------ Baidu Search ----------- https://cloud.baidu.com/doc/qianfan-api/s/Wmbq4z7e5 +# AGENT_BAIDU_SEARCH_API_KEY= + #------ Serply.io ----------- https://serply.io/ # AGENT_SERPLY_API_KEY= @@ -448,4 +451,4 @@ GID='1000' # (optional) Comma-separated list of skills that are auto-approved. # This will allow the skill to be invoked without user interaction. -# AGENT_AUTO_APPROVED_SKILLS=create-pdf-file,create-word-file \ No newline at end of file +# AGENT_AUTO_APPROVED_SKILLS=create-pdf-file,create-word-file diff --git a/frontend/src/pages/Admin/Agents/WebSearchSelection/SearchProviderOptions/index.jsx b/frontend/src/pages/Admin/Agents/WebSearchSelection/SearchProviderOptions/index.jsx index 1d246bdc..17c63fbe 100644 --- a/frontend/src/pages/Admin/Agents/WebSearchSelection/SearchProviderOptions/index.jsx +++ b/frontend/src/pages/Admin/Agents/WebSearchSelection/SearchProviderOptions/index.jsx @@ -248,6 +248,43 @@ export function BingSearchOptions({ settings }) { ); } +export function BaiduSearchOptions({ settings }) { + return ( + <> +

+ You can get an API key{" "} + + from Baidu AI Cloud Qianfan. + +

+
+
+ + +
+
+ + ); +} + export function SerplySearchOptions({ settings }) { return ( <> diff --git a/frontend/src/pages/Admin/Agents/WebSearchSelection/icons/baidu.png b/frontend/src/pages/Admin/Agents/WebSearchSelection/icons/baidu.png new file mode 100644 index 0000000000000000000000000000000000000000..7d57538d33b151148b2e88a704e5f28fedc68669 GIT binary patch literal 40238 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≶25qq$Mdy4pkdlT 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 literal 0 HcmV?d00001 diff --git a/frontend/src/pages/Admin/Agents/WebSearchSelection/index.jsx b/frontend/src/pages/Admin/Agents/WebSearchSelection/index.jsx index 11a58edb..44803381 100644 --- a/frontend/src/pages/Admin/Agents/WebSearchSelection/index.jsx +++ b/frontend/src/pages/Admin/Agents/WebSearchSelection/index.jsx @@ -4,6 +4,7 @@ import SerpApiIcon from "./icons/serpapi.png"; import SearchApiIcon from "./icons/searchapi.png"; import SerperDotDevIcon from "./icons/serper.png"; import BingSearchIcon from "./icons/bing.png"; +import BaiduSearchIcon from "./icons/baidu.png"; import SerplySearchIcon from "./icons/serply.png"; import SearXNGSearchIcon from "./icons/searxng.png"; import TavilySearchIcon from "./icons/tavily.svg"; @@ -24,6 +25,7 @@ import { SearchApiOptions, SerperDotDevOptions, BingSearchOptions, + BaiduSearchOptions, SerplySearchOptions, SearXNGOptions, TavilySearchOptions, @@ -71,6 +73,14 @@ const SEARCH_PROVIDERS = [ options: (settings) => , description: "Web search powered by the Bing Search API (paid service).", }, + { + name: "Baidu Search", + value: "baidu-search", + logo: BaiduSearchIcon, + options: (settings) => , + description: + "Web search powered by Baidu Search for stronger zh-CN retrieval.", + }, { name: "Serply.io", value: "serply-engine", diff --git a/server/.env.example b/server/.env.example index bf5e519a..9c7878ad 100644 --- a/server/.env.example +++ b/server/.env.example @@ -382,6 +382,9 @@ TTS_PROVIDER="native" #------ Bing Search ----------- https://portal.azure.com/ # AGENT_BING_SEARCH_API_KEY= +#------ Baidu Search ----------- https://cloud.baidu.com/doc/qianfan-api/s/Wmbq4z7e5 +# AGENT_BAIDU_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 c54a3213..4518740d 100644 --- a/server/models/systemSettings.js +++ b/server/models/systemSettings.js @@ -147,6 +147,7 @@ const SystemSettings = { "searchapi", "serper-dot-dev", "bing-search", + "baidu-search", "serply-engine", "searxng-engine", "tavily-search", @@ -483,6 +484,7 @@ const SystemSettings = { AgentSearchApiEngine: process.env.AGENT_SEARCHAPI_ENGINE || "google", AgentSerperApiKey: !!process.env.AGENT_SERPER_DEV_KEY || null, AgentBingSearchApiKey: !!process.env.AGENT_BING_SEARCH_API_KEY || null, + AgentBaiduSearchApiKey: !!process.env.AGENT_BAIDU_SEARCH_API_KEY || null, AgentSerplyApiKey: !!process.env.AGENT_SERPLY_API_KEY || null, AgentSearXNGApiUrl: process.env.AGENT_SEARXNG_API_URL || null, AgentTavilyApiKey: !!process.env.AGENT_TAVILY_API_KEY || null, diff --git a/server/utils/agents/aibitat/plugins/web-browsing.js b/server/utils/agents/aibitat/plugins/web-browsing.js index 5f63fd21..23d5b38c 100644 --- a/server/utils/agents/aibitat/plugins/web-browsing.js +++ b/server/utils/agents/aibitat/plugins/web-browsing.js @@ -80,6 +80,9 @@ const webBrowsing = { case "bing-search": engine = "_bingWebSearch"; break; + case "baidu-search": + engine = "_baiduSearch"; + break; case "serply-engine": engine = "_serplyEngine"; break; @@ -604,6 +607,113 @@ const webBrowsing = { ); return result; }, + _baiduSearch: async function (query) { + if (!process.env.AGENT_BAIDU_SEARCH_API_KEY) { + this.super.introspect( + `${this.caller}: I can't use Baidu Search because the user has not defined the required API key.\nVisit: https://cloud.baidu.com/doc/qianfan-api/s/Wmbq4z7e5 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.`; + } + + this.super.introspect( + `${this.caller}: Using Baidu Search to search for "${ + query.length > 100 ? `${query.slice(0, 100)}...` : query + }"` + ); + + const { response, error } = await fetch( + "https://qianfan.baidubce.com/v2/ai_search/web_search", + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${process.env.AGENT_BAIDU_SEARCH_API_KEY}`, + "X-Appbuilder-Authorization": `Bearer ${process.env.AGENT_BAIDU_SEARCH_API_KEY}`, + }, + body: JSON.stringify({ + messages: [{ role: "user", content: query }], + resource_type_filter: [{ type: "web", top_k: 10 }], + }), + } + ) + .then(async (res) => { + if (res.ok) return res.json(); + + const body = await res.text().catch(() => ""); + throw new Error( + `${res.status} - ${res.statusText}. params: ${JSON.stringify({ + auth: this.middleTruncate( + process.env.AGENT_BAIDU_SEARCH_API_KEY, + 5 + ), + q: query, + body: body.slice(0, 300), + })}` + ); + }) + .then((data) => { + return { response: data, error: null }; + }) + .catch((e) => { + this.super.handlerProps.log(`Baidu Search Error: ${e.message}`); + return { response: null, error: e.message }; + }); + + if (error) + return `There was an error searching for content. ${error}`; + + if ( + (response?.code || response?.message) && + !response?.references + ) { + return `There was an error searching for content. ${response?.message || response?.code}`; + } + + /** + * Normalize Baidu Search References to the expected search results format + * @param {Array} references - The references to normalize + * @returns {Array} The normalized references + */ + function normalizeBaiduSearchReferences(references = []) { + if (!Array.isArray(references)) return []; + + const seenLinks = new Set(); + return references + .filter((reference) => { + if (!reference) return false; + const referenceType = String( + reference.type || reference.resource_type || "web" + ).toLowerCase(); + return referenceType === "web"; + }) + .map((reference) => { + const title = String( + reference.title || reference.web_anchor || "" + ).trim(); + const link = String(reference.url || "").trim(); + const snippet = String( + reference.snippet || reference.content || "" + ).trim(); + + if (!title || !link || seenLinks.has(link)) return null; + seenLinks.add(link); + + return { title, link, snippet }; + }) + .filter(Boolean); + } + + const data = normalizeBaiduSearchReferences(response?.references); + if (data.length === 0) + return `No information was found online for the search query.`; + + this.reportSearchResultsCitations(data); + const result = JSON.stringify(data); + this.super.introspect( + `${this.caller}: I found ${data.length} results - reviewing the results now. (~${this.countTokens(result)} tokens)` + ); + return result; + }, _serplyEngine: async function ( query, language = "en", diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js index ec171e05..de3630c1 100644 --- a/server/utils/helpers/updateENV.js +++ b/server/utils/helpers/updateENV.js @@ -586,6 +586,10 @@ const KEY_MAPPING = { envKey: "AGENT_BING_SEARCH_API_KEY", checks: [], }, + AgentBaiduSearchApiKey: { + envKey: "AGENT_BAIDU_SEARCH_API_KEY", + checks: [], + }, AgentSerplyApiKey: { envKey: "AGENT_SERPLY_API_KEY", checks: [],