rogerserper
commited on
Commit
•
6f7b315
1
Parent(s):
7457e8c
Added Serper.dev API as an alternative web search provider (#302)
Browse files
.env
CHANGED
@@ -8,7 +8,8 @@ MONGODB_DIRECT_CONNECTION=false
|
|
8 |
COOKIE_NAME=hf-chat
|
9 |
HF_ACCESS_TOKEN=#hf_<token> from from https://huggingface.co/settings/token
|
10 |
|
11 |
-
# used to activate search with web functionality. disabled if
|
|
|
12 |
SERPAPI_KEY=#your serpapi key here
|
13 |
|
14 |
# Parameters to enable "Sign in with HF"
|
|
|
8 |
COOKIE_NAME=hf-chat
|
9 |
HF_ACCESS_TOKEN=#hf_<token> from from https://huggingface.co/settings/token
|
10 |
|
11 |
+
# used to activate search with web functionality. disabled if none are defined. choose one of the following:
|
12 |
+
SERPER_API_KEY=#your serper.dev api key here
|
13 |
SERPAPI_KEY=#your serpapi key here
|
14 |
|
15 |
# Parameters to enable "Sign in with HF"
|
src/lib/server/websearch/searchWeb.ts
CHANGED
@@ -1,10 +1,53 @@
|
|
1 |
-
import { SERPAPI_KEY } from "$env/static/private";
|
2 |
|
3 |
import { getJson } from "serpapi";
|
4 |
import type { GoogleParameters } from "serpapi";
|
5 |
|
6 |
// Show result as JSON
|
7 |
export async function searchWeb(query: string) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
const params = {
|
9 |
q: query,
|
10 |
hl: "en",
|
|
|
1 |
+
import { SERPAPI_KEY, SERPER_API_KEY } from "$env/static/private";
|
2 |
|
3 |
import { getJson } from "serpapi";
|
4 |
import type { GoogleParameters } from "serpapi";
|
5 |
|
6 |
// Show result as JSON
|
7 |
export async function searchWeb(query: string) {
|
8 |
+
if (SERPER_API_KEY) {
|
9 |
+
return await searchWebSerper(query);
|
10 |
+
}
|
11 |
+
if (SERPAPI_KEY) {
|
12 |
+
return await searchWebSerpApi(query);
|
13 |
+
}
|
14 |
+
throw new Error("No Serper.dev or SerpAPI key found");
|
15 |
+
}
|
16 |
+
|
17 |
+
export async function searchWebSerper(query: string) {
|
18 |
+
const params = {
|
19 |
+
q: query,
|
20 |
+
hl: "en",
|
21 |
+
gl: "us",
|
22 |
+
};
|
23 |
+
|
24 |
+
const response = await fetch("https://google.serper.dev/search", {
|
25 |
+
method: "POST",
|
26 |
+
body: JSON.stringify(params),
|
27 |
+
headers: {
|
28 |
+
"x-api-key": SERPER_API_KEY,
|
29 |
+
"Content-type": "application/json; charset=UTF-8",
|
30 |
+
},
|
31 |
+
});
|
32 |
+
|
33 |
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
34 |
+
const data = (await response.json()) as Record<string, any>;
|
35 |
+
|
36 |
+
if (!response.ok) {
|
37 |
+
throw new Error(
|
38 |
+
data["message"] ??
|
39 |
+
`Serper API returned error code ${response.status} - ${response.statusText}`
|
40 |
+
);
|
41 |
+
}
|
42 |
+
|
43 |
+
return {
|
44 |
+
organic_results: data["organic"] ?? [],
|
45 |
+
knowledge_graph: data["knowledgeGraph"] ?? null,
|
46 |
+
answer_box: data["answerBox"] ?? null,
|
47 |
+
};
|
48 |
+
}
|
49 |
+
|
50 |
+
export async function searchWebSerpApi(query: string) {
|
51 |
const params = {
|
52 |
q: query,
|
53 |
hl: "en",
|
src/lib/types/WebSearch.ts
CHANGED
@@ -12,6 +12,7 @@ export interface WebSearch extends Timestamps {
|
|
12 |
searchQuery: string;
|
13 |
results: string[];
|
14 |
knowledgeGraph: string;
|
|
|
15 |
summary: string;
|
16 |
|
17 |
messages: WebSearchMessage[];
|
|
|
12 |
searchQuery: string;
|
13 |
results: string[];
|
14 |
knowledgeGraph: string;
|
15 |
+
answerBox: string;
|
16 |
summary: string;
|
17 |
|
18 |
messages: WebSearchMessage[];
|
src/routes/+layout.server.ts
CHANGED
@@ -6,7 +6,7 @@ import { UrlDependency } from "$lib/types/UrlDependency";
|
|
6 |
import { defaultModel, models, oldModels, validateModel } from "$lib/server/models";
|
7 |
import { authCondition, requiresUser } from "$lib/server/auth";
|
8 |
import { DEFAULT_SETTINGS } from "$lib/types/Settings";
|
9 |
-
import { SERPAPI_KEY } from "$env/static/private";
|
10 |
|
11 |
export const load: LayoutServerLoad = async ({ locals, depends, url }) => {
|
12 |
const { conversations } = collections;
|
@@ -61,7 +61,7 @@ export const load: LayoutServerLoad = async ({ locals, depends, url }) => {
|
|
61 |
DEFAULT_SETTINGS.shareConversationsWithModelAuthors,
|
62 |
ethicsModalAcceptedAt: settings?.ethicsModalAcceptedAt ?? null,
|
63 |
activeModel: settings?.activeModel ?? DEFAULT_SETTINGS.activeModel,
|
64 |
-
searchEnabled: !!SERPAPI_KEY,
|
65 |
},
|
66 |
models: models.map((model) => ({
|
67 |
id: model.id,
|
|
|
6 |
import { defaultModel, models, oldModels, validateModel } from "$lib/server/models";
|
7 |
import { authCondition, requiresUser } from "$lib/server/auth";
|
8 |
import { DEFAULT_SETTINGS } from "$lib/types/Settings";
|
9 |
+
import { SERPAPI_KEY, SERPER_API_KEY } from "$env/static/private";
|
10 |
|
11 |
export const load: LayoutServerLoad = async ({ locals, depends, url }) => {
|
12 |
const { conversations } = collections;
|
|
|
61 |
DEFAULT_SETTINGS.shareConversationsWithModelAuthors,
|
62 |
ethicsModalAcceptedAt: settings?.ethicsModalAcceptedAt ?? null,
|
63 |
activeModel: settings?.activeModel ?? DEFAULT_SETTINGS.activeModel,
|
64 |
+
searchEnabled: !!(SERPAPI_KEY || SERPER_API_KEY),
|
65 |
},
|
66 |
models: models.map((model) => ({
|
67 |
id: model.id,
|
src/routes/conversation/[id]/web-search/+server.ts
CHANGED
@@ -50,6 +50,7 @@ export async function GET({ params, locals, url }) {
|
|
50 |
prompt: prompt,
|
51 |
searchQuery: "",
|
52 |
knowledgeGraph: "",
|
|
|
53 |
results: [],
|
54 |
summary: "",
|
55 |
messages: [],
|
@@ -79,7 +80,12 @@ export async function GET({ params, locals, url }) {
|
|
79 |
results.organic_results.map((el: { link: string }) => el.link)) ??
|
80 |
[];
|
81 |
|
82 |
-
if (results.
|
|
|
|
|
|
|
|
|
|
|
83 |
// if google returns a knowledge graph, we use it
|
84 |
webSearch.knowledgeGraph = JSON.stringify(removeLinks(results.knowledge_graph));
|
85 |
text = webSearch.knowledgeGraph;
|
|
|
50 |
prompt: prompt,
|
51 |
searchQuery: "",
|
52 |
knowledgeGraph: "",
|
53 |
+
answerBox: "",
|
54 |
results: [],
|
55 |
summary: "",
|
56 |
messages: [],
|
|
|
80 |
results.organic_results.map((el: { link: string }) => el.link)) ??
|
81 |
[];
|
82 |
|
83 |
+
if (results.answer_box) {
|
84 |
+
// if google returns an answer box, we use it
|
85 |
+
webSearch.answerBox = JSON.stringify(removeLinks(results.answer_box));
|
86 |
+
text = webSearch.answerBox;
|
87 |
+
appendUpdate("Found a Google answer box");
|
88 |
+
} else if (results.knowledge_graph) {
|
89 |
// if google returns a knowledge graph, we use it
|
90 |
webSearch.knowledgeGraph = JSON.stringify(removeLinks(results.knowledge_graph));
|
91 |
text = webSearch.knowledgeGraph;
|