mirror of
https://github.com/Mintplex-Labs/anything-llm
synced 2026-04-25 17:15:37 +02:00
[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 <rambat1010@gmail.com>
This commit is contained in:
@@ -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=
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
Reference in New Issue
Block a user