Skip to content

Commit 2b709da

Browse files
Add SearchApi to web browsing
1 parent 5c40419 commit 2b709da

File tree

10 files changed

+156
-0
lines changed

10 files changed

+156
-0
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"Qdrant",
4242
"royalblue",
4343
"searxng",
44+
"SearchApi",
4445
"Serper",
4546
"Serply",
4647
"streamable",

docker/.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ GID='1000'
252252
# AGENT_GSE_KEY=
253253
# AGENT_GSE_CTX=
254254

255+
#------ SearchApi.io ----------- https://www.searchapi.io/
256+
# AGENT_SEARCHAPI_API_KEY=
257+
255258
#------ Serper.dev ----------- https://serper.dev/
256259
# AGENT_SERPER_DEV_KEY=
257260

docker/HOW_TO_USE_DOCKER.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ services:
117117
- WHISPER_PROVIDER=local
118118
- TTS_PROVIDER=native
119119
- PASSWORDMINCHAR=8
120+
- AGENT_SEARCHAPI_API_KEY="SearchApi API KEY"
120121
- AGENT_SERPER_DEV_KEY="SERPER DEV API KEY"
121122
- AGENT_SERPLY_API_KEY="Serply.io API KEY"
122123
volumes:

frontend/src/pages/Admin/Agents/WebSearchSelection/SearchProviderOptions/index.jsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,56 @@ export function GoogleSearchOptions({ settings }) {
5050
);
5151
}
5252

53+
export function SearchApiOptions({ settings }) {
54+
return (
55+
<>
56+
<p className="text-sm text-white/60 my-2">
57+
You can get a free API key{" "}
58+
<a
59+
href="https://www.searchapi.io/"
60+
target="_blank"
61+
rel="noreferrer"
62+
className="text-blue-300 underline"
63+
>
64+
from SearchApi.
65+
</a>
66+
</p>
67+
<div className="flex gap-x-4">
68+
<div className="flex flex-col w-60">
69+
<label className="text-white text-sm font-semibold block mb-3">
70+
API Key
71+
</label>
72+
<input
73+
type="password"
74+
name="env::AgentSearchApiKey"
75+
className="border-none bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
76+
placeholder="SearchApi API Key"
77+
defaultValue={settings?.AgentSearchApiKey ? "*".repeat(20) : ""}
78+
required={true}
79+
autoComplete="off"
80+
spellCheck={false}
81+
/>
82+
</div>
83+
<div className="flex flex-col w-60">
84+
<label className="text-white text-sm font-semibold block mb-3">
85+
Engine
86+
</label>
87+
<input
88+
type="text"
89+
name="env::AgentSearchApiEngine"
90+
className="border-none bg-zinc-900 text-white placeholder:text-white/20 text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5"
91+
placeholder="SearchApi engine (Google, Bing...)"
92+
defaultValue={settings?.AgentSearchApiEngine || "google"}
93+
required={true}
94+
autoComplete="off"
95+
spellCheck={false}
96+
/>
97+
</div>
98+
</div>
99+
</>
100+
);
101+
}
102+
53103
export function SerperDotDevOptions({ settings }) {
54104
return (
55105
<>
4.37 KB
Loading

frontend/src/pages/Admin/Agents/WebSearchSelection/index.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useEffect, useRef, useState } from "react";
22
import AnythingLLMIcon from "@/media/logo/anything-llm-icon.png";
33
import GoogleSearchIcon from "./icons/google.png";
4+
import SearchApiIcon from "./icons/searchapi.png";
45
import SerperDotDevIcon from "./icons/serper.png";
56
import BingSearchIcon from "./icons/bing.png";
67
import SerplySearchIcon from "./icons/serply.png";
@@ -14,6 +15,7 @@ import {
1415
import SearchProviderItem from "./SearchProviderItem";
1516
import WebSearchImage from "@/media/agents/scrape-websites.png";
1617
import {
18+
SearchApiOptions,
1719
SerperDotDevOptions,
1820
GoogleSearchOptions,
1921
BingSearchOptions,
@@ -38,6 +40,14 @@ const SEARCH_PROVIDERS = [
3840
description:
3941
"Web search powered by a custom Google Search Engine. Free for 100 queries per day.",
4042
},
43+
{
44+
name: "SearchApi",
45+
value: "searchapi",
46+
logo: SearchApiIcon,
47+
options: (settings) => <SearchApiOptions settings={settings} />,
48+
description:
49+
"SearchApi delivers structured data from search engines like Google Search, Bing Search, Baidu Search, Google News, YouTube, and many more. Free for 100 queries, but then paid. ",
50+
},
4151
{
4252
name: "Serper.dev",
4353
value: "serper-dot-dev",

server/.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ TTS_PROVIDER="native"
241241
# AGENT_GSE_KEY=
242242
# AGENT_GSE_CTX=
243243

244+
#------ SearchApi.io ----------- https://www.searchapi.io/
245+
# AGENT_SEARCHAPI_API_KEY=
246+
244247
#------ Serper.dev ----------- https://serper.dev/
245248
# AGENT_SERPER_DEV_KEY=
246249

server/models/systemSettings.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ const SystemSettings = {
8181
if (
8282
![
8383
"google-search-engine",
84+
"searchapi",
8485
"serper-dot-dev",
8586
"bing-search",
8687
"serply-engine",
@@ -218,6 +219,8 @@ const SystemSettings = {
218219
// --------------------------------------------------------
219220
AgentGoogleSearchEngineId: process.env.AGENT_GSE_CTX || null,
220221
AgentGoogleSearchEngineKey: !!process.env.AGENT_GSE_KEY || null,
222+
AgentSearchApiKey: !!process.env.AGENT_SEARCHAPI_API_KEY || null,
223+
AgentSearchApiEngine: process.env.AGENT_SEARCHAPI_ENGINE || "google",
221224
AgentSerperApiKey: !!process.env.AGENT_SERPER_DEV_KEY || null,
222225
AgentBingSearchApiKey: !!process.env.AGENT_BING_SEARCH_API_KEY || null,
223226
AgentSerplyApiKey: !!process.env.AGENT_SERPLY_API_KEY || null,

server/utils/agents/aibitat/plugins/web-browsing.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ const webBrowsing = {
6262
case "google-search-engine":
6363
engine = "_googleSearchEngine";
6464
break;
65+
case "searchapi":
66+
engine = "_searchApi";
67+
break;
6568
case "serper-dot-dev":
6669
engine = "_serperDotDev";
6770
break;
@@ -130,6 +133,80 @@ const webBrowsing = {
130133
return JSON.stringify(data);
131134
},
132135

136+
/**
137+
* Use SearchApi
138+
* SearchApi supports multiple search engines like Google Search, Bing Search, Baidu Search, Google News, YouTube, and many more.
139+
* https://www.searchapi.io/
140+
*/
141+
_searchApi: async function (query) {
142+
if (!process.env.AGENT_SEARCHAPI_API_KEY) {
143+
this.super.introspect(
144+
`${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.`
145+
);
146+
return `Search is disabled and no content was found. This functionality is disabled because the user has not set it up yet.`;
147+
}
148+
149+
this.super.introspect(
150+
`${this.caller}: Using SearchApi to search for "${
151+
query.length > 100 ? `${query.slice(0, 100)}...` : query
152+
}"`
153+
);
154+
155+
const engine = process.env.AGENT_SEARCHAPI_ENGINE;
156+
const params = new URLSearchParams({
157+
engine: engine,
158+
q: query,
159+
});
160+
161+
const url = `https://www.searchapi.io/api/v1/search?${params.toString()}`;
162+
const { response, error } = await fetch(url, {
163+
method: "GET",
164+
headers: {
165+
"Authorization": `Bearer ${process.env.AGENT_SEARCHAPI_API_KEY}`,
166+
"Content-Type": "application/json",
167+
"X-SearchApi-Source": "AnythingLLM",
168+
},
169+
})
170+
.then((res) => res.json())
171+
.then((data) => {
172+
if (data?.message === "Unauthorized") {
173+
return {
174+
response: null,
175+
error:
176+
"Unauthorized. Please double check your AGENT_SEARCHAPI_API_KEY",
177+
};
178+
}
179+
return { response: data, error: null };
180+
})
181+
.catch((e) => {
182+
return { response: null, error: e.message };
183+
});
184+
if (error)
185+
return `There was an error searching for content. ${error}`;
186+
187+
const data = [];
188+
if (response.hasOwnProperty("knowledge_graph"))
189+
data.push(response.knowledge_graph);
190+
if (response.hasOwnProperty("answer_box"))
191+
data.push(response.answer_box.answer);
192+
response.organic_results?.forEach((searchResult) => {
193+
const { title, link, snippet } = searchResult;
194+
data.push({
195+
title,
196+
link,
197+
snippet,
198+
});
199+
});
200+
console.log (data);
201+
202+
if (data.length === 0)
203+
return `No information was found online for the search query.`;
204+
this.super.introspect(
205+
`${this.caller}: I found ${data.length} results - looking over them now.`
206+
);
207+
return JSON.stringify(data);
208+
},
209+
133210
/**
134211
* Use Serper.dev
135212
* Free to set up, easy to use, 2,500 calls for free one-time

server/utils/helpers/updateENV.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,14 @@ const KEY_MAPPING = {
435435
envKey: "AGENT_GSE_KEY",
436436
checks: [],
437437
},
438+
AgentSearchApiKey: {
439+
envKey: "AGENT_SEARCHAPI_API_KEY",
440+
checks: [],
441+
},
442+
AgentSearchApiEngine: {
443+
envKey: "AGENT_SEARCHAPI_ENGINE",
444+
checks: [],
445+
},
438446
AgentSerperApiKey: {
439447
envKey: "AGENT_SERPER_DEV_KEY",
440448
checks: [],

0 commit comments

Comments
 (0)