aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/chatbot/tools/SearchTool.ts
blob: 8e6edce8c27aaffa20b6b86f2ad710de6b04ec6f (plain)
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
import { v4 as uuidv4 } from 'uuid';
import { Networking } from '../../../../Network';
import { BaseTool } from './BaseTool';
import { Observation } from '../types/types';
import { ParametersType, ToolInfo } from '../types/tool_types';
import { Agent } from 'http';
import { AgentDocumentManager } from '../utils/AgentDocumentManager';
import { StrCast } from '../../../../../fields/Types';

const searchToolParams = [
    {
        name: 'queries',
        type: 'string[]',
        description:
            'The search query or queries to use for finding websites. Provide up to 3 search queries to find a broad range of websites. Should be in the form of a TypeScript array of strings (e.g. <queries>["search term 1", "search term 2", "search term 3"]</queries>).',
        required: true,
        max_inputs: 3,
    },
] as const;

type SearchToolParamsType = typeof searchToolParams;

const searchToolInfo: ToolInfo<SearchToolParamsType> = {
    name: 'searchTool',
    citationRules: 'Always cite the search results for a response, if the search results are relevant to the response. Use the chunk_id to cite the search results. If the search results are not relevant to the response, do not cite them.   ',
    parameterRules: searchToolParams,
    description: 'Search the web to find a wide range of websites related to a query or multiple queries. Returns a list of websites and their overviews based on the search queries.',
};

export class SearchTool extends BaseTool<SearchToolParamsType> {
    private _docManager: AgentDocumentManager;
    private _max_results: number;

    constructor(docManager: AgentDocumentManager, max_results: number = 3) {
        super(searchToolInfo);
        this._docManager = docManager;
        this._max_results = max_results;
    }

    async execute(args: ParametersType<SearchToolParamsType>): Promise<Observation[]> {
        const queries = args.queries;

        console.log(`Searching the web for queries: ${queries[0]}`);
        // Create an array of promises, each one handling a search for a query
        const searchPromises = queries.map(async query => {
            try {
                const { results } = (await Networking.PostToServer('/getWebSearchResults', {
                    query,
                    max_results: this._max_results,
                })) as { results: { url: string; snippet: string }[] };
                const data = await Promise.all(
                    results.map(async (result: { url: string; snippet: string }) => {
                        // Create a web document with the URL
                        const id = await this._docManager.createDocInDash('web', result.url, {
                            title: `Search Result: ${result.url}`,
                            text_html: result.snippet,
                            data_useCors: true,
                        });

                        return {
                            type: 'text' as const,
                            text: `<chunk chunk_id="${id}" chunk_type="url"><url>${result.url}</url><overview>${result.snippet}</overview></chunk>`,
                        };
                    })
                );
                return data;
            } catch (error) {
                console.log(error);
                return [
                    {
                        type: 'text' as const,
                        text: `An error occurred while performing the web search for query: ${query}`,
                    },
                ];
            }
        });

        const allResultsArrays = await Promise.all(searchPromises);

        return allResultsArrays.flat();
    }
}