-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
serper.ts
107 lines (86 loc) · 2.44 KB
/
serper.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import { getEnvironmentVariable } from "@langchain/core/utils/env";
import { Tool } from "@langchain/core/tools";
/**
* Defines the parameters that can be passed to the Serper class during
* instantiation. It includes `gl` and `hl` which are optional.
*/
export type SerperParameters = {
gl?: string;
hl?: string;
};
/**
* Wrapper around serper.
*
* You can create a free API key at https://serper.dev.
*
* To use, you should have the SERPER_API_KEY environment variable set.
*/
export class Serper extends Tool {
static lc_name() {
return "Serper";
}
/**
* Converts the Serper instance to JSON. This method is not implemented
* and will throw an error if called.
* @returns Throws an error.
*/
toJSON() {
return this.toJSONNotImplemented();
}
protected key: string;
protected params: Partial<SerperParameters>;
constructor(
apiKey: string | undefined = getEnvironmentVariable("SERPER_API_KEY"),
params: Partial<SerperParameters> = {}
) {
super();
if (!apiKey) {
throw new Error(
"Serper API key not set. You can set it as SERPER_API_KEY in your .env file, or pass it to Serper."
);
}
this.key = apiKey;
this.params = params;
}
name = "search";
/** @ignore */
async _call(input: string) {
const options = {
method: "POST",
headers: {
"X-API-KEY": this.key,
"Content-Type": "application/json",
},
body: JSON.stringify({
q: input,
...this.params,
}),
};
const res = await fetch("https://google.serper.dev/search", options);
if (!res.ok) {
throw new Error(`Got ${res.status} error from serper: ${res.statusText}`);
}
const json = await res.json();
if (json.answerBox?.answer) {
return json.answerBox.answer;
}
if (json.answerBox?.snippet) {
return json.answerBox.snippet;
}
if (json.answerBox?.snippet_highlighted_words) {
return json.answerBox.snippet_highlighted_words[0];
}
if (json.sportsResults?.game_spotlight) {
return json.sportsResults.game_spotlight;
}
if (json.knowledgeGraph?.description) {
return json.knowledgeGraph.description;
}
if (json.organic?.[0]?.snippet) {
return json.organic[0].snippet;
}
return "No good search result found";
}
description =
"a search engine. useful for when you need to answer questions about current events. input should be a search query.";
}