File size: 3,434 Bytes
755dd12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { EndPoint, DEFAULT_SEARCH_ENGINE_TIMEOUT, BING_MKT } from './utils/constant';
import { httpRequest } from './utils/utils';
import { Sogou } from './search/sogou';
import searxng, { ESearXNGCategory } from './search/searxng';
import { webSearch } from './search/chatglm';


export const searchWithSearXNG = async (
  query: string,
  categories?: ESearXNGCategory[],
  language = 'all'
) => {
  language = process.env.SEARXNG_LANGUAGE || language;
  const defaultEngines = process.env.SEARXNG_ENGINES ? process.env.SEARXNG_ENGINES.split(',') : [];
  const engines = defaultEngines.map(item => item.trim());
  // Scientific search only supports english, so set to all.
  if (categories?.includes(ESearXNGCategory.SCIENCE)) language = 'all';
  const res = await searxng({
    q: query,
    categories,
    language,
    engines: engines.join(',')
  });
  return res;
};

/**
 * Search with bing and return the contexts.
 */
export const searchWithBing = async (query: string) => {
  try {
    const subscriptionKey = process.env.BING_SEARCH_KEY;
    if (!subscriptionKey) {
      throw new Error('Bing search key is not provided.');
    }
    const res = await httpRequest({
      endpoint: EndPoint.BING_SEARCH_V7_ENDPOINT,
      timeout: DEFAULT_SEARCH_ENGINE_TIMEOUT,
      query: {
        q: query,
        mkt: BING_MKT
      },
      headers: {
        'Ocp-Apim-Subscription-Key': subscriptionKey
      }
    });
    const result = await res.json();
    const list = result?.webPages?.value || [];
    return list.map((item: any, index: number) => {
      return {
        id: index + 1,
        name: item.name,
        url: item.url,
        snippet: item.snippet
      };
    });
  } catch(err) {
    console.error('[Bing Search Error]:', err);
    return [];
  }
};

/**
 * Search with google and return the contexts.
 */
export const searchWithGoogle = async (query: string) => {
  if (!query.trim()) return [];
  try {
    const key = process.env.GOOGLE_SEARCH_KEY;
    const id = process.env.GOOGLE_SEARCH_ID;
    const res = await httpRequest({
      method: 'GET',
      endpoint: EndPoint.GOOGLE_SEARCH_ENDPOINT,
      query: {
        key,
        cx: id,
        q: query
      },
      timeout: DEFAULT_SEARCH_ENGINE_TIMEOUT
    });
    const result = await res.json();
    const list = result.items ?? [];
    return list.map((item: any, index: number) => {
      return {
        id: index + 1,
        name: item.title,
        url: item.link,
        formattedUrl: item.formattedUrl,
        snippet: item.snippet,
        imageLink: item.image?.thumbnailLink,
        imageContextLink: item.image?.contextLink
      };
    });
  } catch (err) {
    console.error('Google Search Error:', err);
    return [];
  }
};

/**
 * search with sogou and return the contexts.
 */
export const searchWithSogou = async (query: string) => {
  const sogou = new Sogou(query);
  await sogou.init();
  // const relatedQueries = sogou.getRelatedQueries();
  const results = await sogou.getResults();
  return results.map((item, index) => {
    return {
      id: index + 1,
      ...item
    };
  });
};

export const searchWithChatGLM = async (query: string) => {
  const results = await webSearch(query);
  return results.map((item, index) => {
    return {
      id: index + 1,
      name: item.title,
      url: item.link,
      snippet: item.content,
      icon: item.icon,
      media: item.media,
    };
  });
};