From adb99fec1cf30ecee69bb5a65715f1614afbfaf1 Mon Sep 17 00:00:00 2001 From: ed23x <140010230+ed23x@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:34:49 +0100 Subject: [PATCH] Add web browsing feature to LLM Related to #326 --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/coleam00/bolt.new-any-llm/issues/326?shareId=XXXX-XXXX-XXXX-XXXX). --- app/lib/.server/llm/model.ts | 18 ++++++++++++++++-- app/lib/.server/llm/stream-text.ts | 2 -- app/routes/api.chat.ts | 3 +-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/lib/.server/llm/model.ts b/app/lib/.server/llm/model.ts index 6be9d1170..25573eb5d 100644 --- a/app/lib/.server/llm/model.ts +++ b/app/lib/.server/llm/model.ts @@ -1,5 +1,3 @@ -// @ts-nocheck -// Preventing TS checks with files presented in the video for a better presentation. import { getAPIKey, getBaseURL } from '~/lib/.server/llm/api-key'; import { createAnthropic } from '@ai-sdk/anthropic'; import { createOpenAI } from '@ai-sdk/openai'; @@ -7,6 +5,7 @@ import { createGoogleGenerativeAI } from '@ai-sdk/google'; import { ollama } from 'ollama-ai-provider'; import { createOpenRouter } from "@openrouter/ai-sdk-provider"; import { createMistral } from '@ai-sdk/mistral'; +import { chromium } from 'playwright'; export function getAnthropicModel(apiKey: string, model: string) { const anthropic = createAnthropic({ @@ -99,6 +98,19 @@ export function getXAIModel(apiKey: string, model: string) { return openai(model); } + +export async function getWebBrowsingModel(query: string) { + const browser = await chromium.launch(); + const page = await browser.newPage(); + await page.goto('https://duckduckgo.com/'); + await page.fill('input[name="q"]', query); + await page.press('input[name="q"]', 'Enter'); + await page.waitForSelector('#links .result__a'); + const results = await page.$$eval('#links .result__a', links => links.map(link => link.textContent)); + await browser.close(); + return results; +} + export function getModel(provider: string, model: string, env: Env, apiKeys?: Record) { const apiKey = getAPIKey(env, provider, apiKeys); const baseURL = getBaseURL(env, provider); @@ -124,6 +136,8 @@ export function getModel(provider: string, model: string, env: Env, apiKeys?: Re return getLMStudioModel(baseURL, model); case 'xAI': return getXAIModel(apiKey, model); + case 'WebBrowsing': + return getWebBrowsingModel; default: return getOllamaModel(baseURL, model); } diff --git a/app/lib/.server/llm/stream-text.ts b/app/lib/.server/llm/stream-text.ts index 8bfd79786..666501492 100644 --- a/app/lib/.server/llm/stream-text.ts +++ b/app/lib/.server/llm/stream-text.ts @@ -1,5 +1,3 @@ -// @ts-nocheck -// Preventing TS checks with files presented in the video for a better presentation. import { streamText as _streamText, convertToCoreMessages } from 'ai'; import { getModel } from '~/lib/.server/llm/model'; import { MAX_TOKENS } from './constants'; diff --git a/app/routes/api.chat.ts b/app/routes/api.chat.ts index 47666c703..670815a5f 100644 --- a/app/routes/api.chat.ts +++ b/app/routes/api.chat.ts @@ -1,10 +1,9 @@ -// @ts-nocheck -// Preventing TS checks with files presented in the video for a better presentation. import { type ActionFunctionArgs } from '@remix-run/cloudflare'; import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '~/lib/.server/llm/constants'; import { CONTINUE_PROMPT } from '~/lib/.server/llm/prompts'; import { streamText, type Messages, type StreamingOptions } from '~/lib/.server/llm/stream-text'; import SwitchableStream from '~/lib/.server/llm/switchable-stream'; +import { getWebBrowsingModel } from '~/lib/.server/llm/model'; export async function action(args: ActionFunctionArgs) { return chatAction(args);