agsamantha/node_modules/@langchain/community/dist/tools/serpapi.cjs

202 lines
7.2 KiB
JavaScript
Raw Normal View History

2024-10-02 20:15:21 +00:00
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SerpAPI = void 0;
const env_1 = require("@langchain/core/utils/env");
const tools_1 = require("@langchain/core/tools");
/**
* Wrapper around SerpAPI.
*
* To use, you should have the `serpapi` package installed and the SERPAPI_API_KEY environment variable set.
*/
class SerpAPI extends tools_1.Tool {
static lc_name() {
return "SerpAPI";
}
toJSON() {
return this.toJSONNotImplemented();
}
constructor(apiKey = (0, env_1.getEnvironmentVariable)("SERPAPI_API_KEY"), params = {}, baseUrl = "https://serpapi.com") {
super(...arguments);
Object.defineProperty(this, "key", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "params", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "baseUrl", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "name", {
enumerable: true,
configurable: true,
writable: true,
value: "search"
});
Object.defineProperty(this, "description", {
enumerable: true,
configurable: true,
writable: true,
value: "a search engine. useful for when you need to answer questions about current events. input should be a search query."
});
if (!apiKey) {
throw new Error("SerpAPI API key not set. You can set it as SERPAPI_API_KEY in your .env file, or pass it to SerpAPI.");
}
this.key = apiKey;
this.params = params;
this.baseUrl = baseUrl;
}
/**
* Builds a URL for the SerpAPI request.
* @param path The path for the request.
* @param parameters The parameters for the request.
* @param baseUrl The base URL for the request.
* @returns A string representing the built URL.
*/
buildUrl(path, parameters, baseUrl) {
const nonUndefinedParams = Object.entries(parameters)
.filter(([_, value]) => value !== undefined)
.map(([key, value]) => [key, `${value}`]);
const searchParams = new URLSearchParams(nonUndefinedParams);
return `${baseUrl}/${path}?${searchParams}`;
}
/** @ignore */
async _call(input) {
const { timeout, ...params } = this.params;
const resp = await fetch(this.buildUrl("search", {
...params,
api_key: this.key,
q: input,
}, this.baseUrl), {
signal: timeout ? AbortSignal.timeout(timeout) : undefined,
});
const res = await resp.json();
if (res.error) {
throw new Error(`Got error from serpAPI: ${res.error}`);
}
const answer_box = res.answer_box_list
? res.answer_box_list[0]
: res.answer_box;
if (answer_box) {
if (answer_box.result) {
return answer_box.result;
}
else if (answer_box.answer) {
return answer_box.answer;
}
else if (answer_box.snippet) {
return answer_box.snippet;
}
else if (answer_box.snippet_highlighted_words) {
return answer_box.snippet_highlighted_words.toString();
}
else {
const answer = {};
Object.keys(answer_box)
.filter((k) => !Array.isArray(answer_box[k]) &&
typeof answer_box[k] !== "object" &&
!(typeof answer_box[k] === "string" &&
answer_box[k].startsWith("http")))
.forEach((k) => {
answer[k] = answer_box[k];
});
return JSON.stringify(answer);
}
}
if (res.events_results) {
return JSON.stringify(res.events_results);
}
if (res.sports_results) {
return JSON.stringify(res.sports_results);
}
if (res.top_stories) {
return JSON.stringify(res.top_stories);
}
if (res.news_results) {
return JSON.stringify(res.news_results);
}
if (res.jobs_results?.jobs) {
return JSON.stringify(res.jobs_results.jobs);
}
if (res.questions_and_answers) {
return JSON.stringify(res.questions_and_answers);
}
if (res.popular_destinations?.destinations) {
return JSON.stringify(res.popular_destinations.destinations);
}
if (res.top_sights?.sights) {
const sights = res.top_sights.sights
.map((s) => ({
title: s.title,
description: s.description,
price: s.price,
}))
.slice(0, 8);
return JSON.stringify(sights);
}
if (res.shopping_results && res.shopping_results[0]?.title) {
return JSON.stringify(res.shopping_results.slice(0, 3));
}
if (res.images_results && res.images_results[0]?.thumbnail) {
return res.images_results
.map((ir) => ir.thumbnail)
.slice(0, 10)
.toString();
}
const snippets = [];
if (res.knowledge_graph) {
if (res.knowledge_graph.description) {
snippets.push(res.knowledge_graph.description);
}
const title = res.knowledge_graph.title || "";
Object.keys(res.knowledge_graph)
.filter((k) => typeof res.knowledge_graph[k] === "string" &&
k !== "title" &&
k !== "description" &&
!k.endsWith("_stick") &&
!k.endsWith("_link") &&
!k.startsWith("http"))
.forEach((k) => snippets.push(`${title} ${k}: ${res.knowledge_graph[k]}`));
}
const first_organic_result = res.organic_results?.[0];
if (first_organic_result) {
if (first_organic_result.snippet) {
snippets.push(first_organic_result.snippet);
}
else if (first_organic_result.snippet_highlighted_words) {
snippets.push(first_organic_result.snippet_highlighted_words);
}
else if (first_organic_result.rich_snippet) {
snippets.push(first_organic_result.rich_snippet);
}
else if (first_organic_result.rich_snippet_table) {
snippets.push(first_organic_result.rich_snippet_table);
}
else if (first_organic_result.link) {
snippets.push(first_organic_result.link);
}
}
if (res.buying_guide) {
snippets.push(res.buying_guide);
}
if (res.local_results?.places) {
snippets.push(res.local_results.places);
}
if (snippets.length > 0) {
return JSON.stringify(snippets);
}
else {
return "No good search result found";
}
}
}
exports.SerpAPI = SerpAPI;