Skip to content

Commit d90571f

Browse files
Add improved logging and introspection to web-browsing (Mintplex-Labs#3140)
1 parent 1bfd461 commit d90571f

File tree

1 file changed

+127
-40
lines changed

1 file changed

+127
-40
lines changed

Diff for: server/utils/agents/aibitat/plugins/web-browsing.js

+127-40
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
const { SystemSettings } = require("../../../../models/systemSettings");
2+
const { TokenManager } = require("../../../helpers/tiktoken");
3+
const tiktoken = new TokenManager();
24

35
const webBrowsing = {
46
name: "web-browsing",
@@ -12,6 +14,11 @@ const webBrowsing = {
1214
aibitat.function({
1315
super: aibitat,
1416
name: this.name,
17+
countTokens: (string) =>
18+
tiktoken
19+
.countFromString(string)
20+
.toString()
21+
.replace(/\B(?=(\d{3})+(?!\d))/g, ","),
1522
description:
1623
"Searches for a given query using a search engine to get better results for the user query.",
1724
examples: [
@@ -89,6 +96,18 @@ const webBrowsing = {
8996
return await this[engine](query);
9097
},
9198

99+
/**
100+
* Utility function to truncate a string to a given length for debugging
101+
* calls to the API while keeping the actual values mostly intact
102+
* @param {string} str - The string to truncate
103+
* @param {number} length - The length to truncate the string to
104+
* @returns {string} The truncated string
105+
*/
106+
middleTruncate(str, length = 5) {
107+
if (str.length <= length) return str;
108+
return `${str.slice(0, length)}...${str.slice(-length)}`;
109+
},
110+
92111
/**
93112
* Use Google Custom Search Engines
94113
* Free to set up, easy to use, 100 calls/day
@@ -115,7 +134,12 @@ const webBrowsing = {
115134
}"`
116135
);
117136
const data = await fetch(searchURL)
118-
.then((res) => res.json())
137+
.then((res) => {
138+
if (res.ok) return res.json();
139+
throw new Error(
140+
`${res.status} - ${res.statusText}. params: ${JSON.stringify({ key: this.middleTruncate(process.env.AGENT_GSE_KEY, 5), cx: this.middleTruncate(process.env.AGENT_GSE_CTX, 5), q: query })}`
141+
);
142+
})
119143
.then((searchResult) => searchResult?.items || [])
120144
.then((items) => {
121145
return items.map((item) => {
@@ -127,16 +151,20 @@ const webBrowsing = {
127151
});
128152
})
129153
.catch((e) => {
130-
console.log(e);
154+
this.super.handlerProps.log(
155+
`${this.name}: Google Search Error: ${e.message}`
156+
);
131157
return [];
132158
});
133159

134160
if (data.length === 0)
135161
return `No information was found online for the search query.`;
162+
163+
const result = JSON.stringify(data);
136164
this.super.introspect(
137-
`${this.caller}: I found ${data.length} results - looking over them now.`
165+
`${this.caller}: I found ${data.length} results - reviewing the results now. (~${this.countTokens(result)} tokens)`
138166
);
139-
return JSON.stringify(data);
167+
return result;
140168
},
141169

142170
/**
@@ -173,11 +201,17 @@ const webBrowsing = {
173201
"X-SearchApi-Source": "AnythingLLM",
174202
},
175203
})
176-
.then((res) => res.json())
204+
.then((res) => {
205+
if (res.ok) return res.json();
206+
throw new Error(
207+
`${res.status} - ${res.statusText}. params: ${JSON.stringify({ auth: this.middleTruncate(process.env.AGENT_SEARCHAPI_API_KEY, 5), q: query })}`
208+
);
209+
})
177210
.then((data) => {
178211
return { response: data, error: null };
179212
})
180213
.catch((e) => {
214+
this.super.handlerProps.log(`SearchApi Error: ${e.message}`);
181215
return { response: null, error: e.message };
182216
});
183217
if (error)
@@ -199,10 +233,12 @@ const webBrowsing = {
199233

200234
if (data.length === 0)
201235
return `No information was found online for the search query.`;
236+
237+
const result = JSON.stringify(data);
202238
this.super.introspect(
203-
`${this.caller}: I found ${data.length} results - looking over them now.`
239+
`${this.caller}: I found ${data.length} results - reviewing the results now. (~${this.countTokens(result)} tokens)`
204240
);
205-
return JSON.stringify(data);
241+
return result;
206242
},
207243

208244
/**
@@ -235,11 +271,17 @@ const webBrowsing = {
235271
redirect: "follow",
236272
}
237273
)
238-
.then((res) => res.json())
274+
.then((res) => {
275+
if (res.ok) return res.json();
276+
throw new Error(
277+
`${res.status} - ${res.statusText}. params: ${JSON.stringify({ auth: this.middleTruncate(process.env.AGENT_SERPER_DEV_KEY, 5), q: query })}`
278+
);
279+
})
239280
.then((data) => {
240281
return { response: data, error: null };
241282
})
242283
.catch((e) => {
284+
this.super.handlerProps.log(`Serper.dev Error: ${e.message}`);
243285
return { response: null, error: e.message };
244286
});
245287
if (error)
@@ -259,10 +301,12 @@ const webBrowsing = {
259301

260302
if (data.length === 0)
261303
return `No information was found online for the search query.`;
304+
305+
const result = JSON.stringify(data);
262306
this.super.introspect(
263-
`${this.caller}: I found ${data.length} results - looking over them now.`
307+
`${this.caller}: I found ${data.length} results - reviewing the results now. (~${this.countTokens(result)} tokens)`
264308
);
265-
return JSON.stringify(data);
309+
return result;
266310
},
267311
_bingWebSearch: async function (query) {
268312
if (!process.env.AGENT_BING_SEARCH_API_KEY) {
@@ -289,7 +333,12 @@ const webBrowsing = {
289333
process.env.AGENT_BING_SEARCH_API_KEY,
290334
},
291335
})
292-
.then((res) => res.json())
336+
.then((res) => {
337+
if (res.ok) return res.json();
338+
throw new Error(
339+
`${res.status} - ${res.statusText}. params: ${JSON.stringify({ auth: this.middleTruncate(process.env.AGENT_BING_SEARCH_API_KEY, 5), q: query })}`
340+
);
341+
})
293342
.then((data) => {
294343
const searchResults = data.webPages?.value || [];
295344
return searchResults.map((result) => ({
@@ -299,16 +348,20 @@ const webBrowsing = {
299348
}));
300349
})
301350
.catch((e) => {
302-
console.log(e);
351+
this.super.handlerProps.log(
352+
`Bing Web Search Error: ${e.message}`
353+
);
303354
return [];
304355
});
305356

306357
if (searchResponse.length === 0)
307358
return `No information was found online for the search query.`;
359+
360+
const result = JSON.stringify(searchResponse);
308361
this.super.introspect(
309-
`${this.caller}: I found ${searchResponse.length} results - looking over them now.`
362+
`${this.caller}: I found ${searchResponse.length} results - reviewing the results now. (~${this.countTokens(result)} tokens)`
310363
);
311-
return JSON.stringify(searchResponse);
364+
return result;
312365
},
313366
_serplyEngine: async function (
314367
query,
@@ -353,20 +406,24 @@ const webBrowsing = {
353406
"X-User-Agent": device_type,
354407
},
355408
})
356-
.then((res) => res.json())
409+
.then((res) => {
410+
if (res.ok) return res.json();
411+
throw new Error(
412+
`${res.status} - ${res.statusText}. params: ${JSON.stringify({ auth: this.middleTruncate(process.env.AGENT_SERPLY_API_KEY, 5), q: query })}`
413+
);
414+
})
357415
.then((data) => {
358-
if (data?.message === "Unauthorized") {
359-
return {
360-
response: null,
361-
error:
362-
"Unauthorized. Please double check your AGENT_SERPLY_API_KEY",
363-
};
364-
}
416+
if (data?.message === "Unauthorized")
417+
throw new Error(
418+
"Unauthorized. Please double check your AGENT_SERPLY_API_KEY"
419+
);
365420
return { response: data, error: null };
366421
})
367422
.catch((e) => {
423+
this.super.handlerProps.log(`Serply Error: ${e.message}`);
368424
return { response: null, error: e.message };
369425
});
426+
370427
if (error)
371428
return `There was an error searching for content. ${error}`;
372429

@@ -382,10 +439,12 @@ const webBrowsing = {
382439

383440
if (data.length === 0)
384441
return `No information was found online for the search query.`;
442+
443+
const result = JSON.stringify(data);
385444
this.super.introspect(
386-
`${this.caller}: I found ${data.length} results - looking over them now.`
445+
`${this.caller}: I found ${data.length} results - reviewing the results now. (~${this.countTokens(result)} tokens)`
387446
);
388-
return JSON.stringify(data);
447+
return result;
389448
},
390449
_searXNGEngine: async function (query) {
391450
let searchURL;
@@ -421,11 +480,19 @@ const webBrowsing = {
421480
"User-Agent": "anything-llm",
422481
},
423482
})
424-
.then((res) => res.json())
483+
.then((res) => {
484+
if (res.ok) return res.json();
485+
throw new Error(
486+
`${res.status} - ${res.statusText}. params: ${JSON.stringify({ url: searchURL.toString() })}`
487+
);
488+
})
425489
.then((data) => {
426490
return { response: data, error: null };
427491
})
428492
.catch((e) => {
493+
this.super.handlerProps.log(
494+
`SearXNG Search Error: ${e.message}`
495+
);
429496
return { response: null, error: e.message };
430497
});
431498
if (error)
@@ -444,10 +511,12 @@ const webBrowsing = {
444511

445512
if (data.length === 0)
446513
return `No information was found online for the search query.`;
514+
515+
const result = JSON.stringify(data);
447516
this.super.introspect(
448-
`${this.caller}: I found ${data.length} results - looking over them now.`
517+
`${this.caller}: I found ${data.length} results - reviewing the results now. (~${this.countTokens(result)} tokens)`
449518
);
450-
return JSON.stringify(data);
519+
return result;
451520
},
452521
_tavilySearch: async function (query) {
453522
if (!process.env.AGENT_TAVILY_API_KEY) {
@@ -474,11 +543,19 @@ const webBrowsing = {
474543
query: query,
475544
}),
476545
})
477-
.then((res) => res.json())
546+
.then((res) => {
547+
if (res.ok) return res.json();
548+
throw new Error(
549+
`${res.status} - ${res.statusText}. params: ${JSON.stringify({ auth: this.middleTruncate(process.env.AGENT_TAVILY_API_KEY, 5), q: query })}`
550+
);
551+
})
478552
.then((data) => {
479553
return { response: data, error: null };
480554
})
481555
.catch((e) => {
556+
this.super.handlerProps.log(
557+
`Tavily Search Error: ${e.message}`
558+
);
482559
return { response: null, error: e.message };
483560
});
484561

@@ -497,10 +574,12 @@ const webBrowsing = {
497574

498575
if (data.length === 0)
499576
return `No information was found online for the search query.`;
577+
578+
const result = JSON.stringify(data);
500579
this.super.introspect(
501-
`${this.caller}: I found ${data.length} results - looking over them now.`
580+
`${this.caller}: I found ${data.length} results - reviewing the results now. (~${this.countTokens(result)} tokens)`
502581
);
503-
return JSON.stringify(data);
582+
return result;
504583
},
505584
_duckDuckGoEngine: async function (query) {
506585
this.super.introspect(
@@ -512,15 +591,23 @@ const webBrowsing = {
512591
const searchURL = new URL("https://html.duckduckgo.com/html");
513592
searchURL.searchParams.append("q", query);
514593

515-
const response = await fetch(searchURL.toString());
516-
517-
if (!response.ok) {
518-
return `There was an error searching DuckDuckGo. Status: ${response.status}`;
519-
}
594+
const response = await fetch(searchURL.toString())
595+
.then((res) => {
596+
if (res.ok) return res.text();
597+
throw new Error(
598+
`${res.status} - ${res.statusText}. params: ${JSON.stringify({ url: searchURL.toString() })}`
599+
);
600+
})
601+
.catch((e) => {
602+
this.super.handlerProps.log(
603+
`DuckDuckGo Search Error: ${e.message}`
604+
);
605+
return null;
606+
});
520607

521-
const html = await response.text();
608+
if (!response) return `There was an error searching DuckDuckGo.`;
609+
const html = response;
522610
const data = [];
523-
524611
const results = html.split('<div class="result results_links');
525612

526613
// Skip first element since it's before the first result
@@ -556,11 +643,11 @@ const webBrowsing = {
556643
return `No information was found online for the search query.`;
557644
}
558645

646+
const result = JSON.stringify(data);
559647
this.super.introspect(
560-
`${this.caller}: I found ${data.length} results - looking over them now.`
648+
`${this.caller}: I found ${data.length} results - reviewing the results now. (~${this.countTokens(result)} tokens)`
561649
);
562-
563-
return JSON.stringify(data);
650+
return result;
564651
},
565652
});
566653
},

0 commit comments

Comments
 (0)