UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

85 lines (68 loc) 2.47 kB
import { SearchParams, SearchQuery } from '@lobechat/types'; import { CrawlImplType, Crawler } from '@lobechat/web-crawler'; import pMap from 'p-map'; import { toolsEnv } from '@/envs/tools'; import { SearchImplType, SearchServiceImpl, createSearchServiceImpl } from './impls'; const parseImplEnv = (envString: string = '') => { // Handle full-width commas and extra whitespace const envValue = envString.replaceAll(',', ',').trim(); return envValue.split(',').filter(Boolean); }; /** * Search service class * Uses different implementations for different search operations */ export class SearchService { private searchImpl: SearchServiceImpl; private get crawlerImpls() { return parseImplEnv(toolsEnv.CRAWLER_IMPLS); } constructor() { const impls = this.searchImpls; // TODO: need use turn mode this.searchImpl = createSearchServiceImpl(impls.length > 0 ? impls[0] : undefined); } async crawlPages(input: { impls?: CrawlImplType[]; urls: string[] }) { const crawler = new Crawler({ impls: this.crawlerImpls }); const results = await pMap( input.urls, async (url) => { return await crawler.crawl({ impls: input.impls, url }); }, { concurrency: 3 }, ); return { results }; } private get searchImpls() { return parseImplEnv(toolsEnv.SEARCH_PROVIDERS) as SearchImplType[]; } /** * Query for search results */ async query(query: string, params?: SearchParams) { return this.searchImpl.query(query, params); } async webSearch({ query, searchCategories, searchEngines, searchTimeRange }: SearchQuery) { let data = await this.query(query, { searchCategories: searchCategories, searchEngines: searchEngines, searchTimeRange: searchTimeRange, }); // First retry: remove search engine restrictions if no results found if (data.results.length === 0 && searchEngines && searchEngines?.length > 0) { const paramsExcludeSearchEngines = { searchCategories: searchCategories, searchEngines: undefined, searchTimeRange: searchTimeRange, }; data = await this.query(query, paramsExcludeSearchEngines); } // Second retry: remove all restrictions if still no results found if (data?.results.length === 0) { data = await this.query(query); } return data; } } // Add a default exported instance for convenience export const searchService = new SearchService();