diff --git a/README.md b/README.md index 8f77369..554858c 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ TODO: add instructions ### Extra -- [ ] Web Search +- [x] Web Search - [ ] Chat branching - [ ] Regenerate message - [ ] Image generation diff --git a/src/lib/backend/convex/conversations.ts b/src/lib/backend/convex/conversations.ts index 0947b43..12c7746 100644 --- a/src/lib/backend/convex/conversations.ts +++ b/src/lib/backend/convex/conversations.ts @@ -131,6 +131,7 @@ export const createAndAddMessage = mutation({ role: args.role, conversation_id: conversationId, session_token: args.session_token, + web_search_enabled: args.web_search_enabled, images: args.images, }); diff --git a/src/lib/backend/convex/messages.ts b/src/lib/backend/convex/messages.ts index 4d41cc7..b7689a6 100644 --- a/src/lib/backend/convex/messages.ts +++ b/src/lib/backend/convex/messages.ts @@ -41,6 +41,7 @@ export const create = mutation({ model_id: v.optional(v.string()), provider: v.optional(providerValidator), token_count: v.optional(v.number()), + web_search_enabled: v.optional(v.boolean()), // Optional image attachments images: v.optional( v.array( @@ -84,6 +85,7 @@ export const create = mutation({ model_id: args.model_id, provider: args.provider, token_count: args.token_count, + web_search_enabled: args.web_search_enabled, // Optional image attachments images: args.images, }), diff --git a/src/lib/backend/convex/schema.ts b/src/lib/backend/convex/schema.ts index 319ccce..11df54b 100644 --- a/src/lib/backend/convex/schema.ts +++ b/src/lib/backend/convex/schema.ts @@ -70,5 +70,6 @@ export default defineSchema({ ), cost_usd: v.optional(v.number()), generation_id: v.optional(v.string()), + web_search_enabled: v.optional(v.boolean()), }).index('by_conversation', ['conversation_id']), }); diff --git a/src/lib/state/settings.svelte.ts b/src/lib/state/settings.svelte.ts index 5daa98d..5e3d33e 100644 --- a/src/lib/state/settings.svelte.ts +++ b/src/lib/state/settings.svelte.ts @@ -2,4 +2,5 @@ import { createPersistedObj } from '$lib/spells/persisted-obj.svelte'; export const settings = createPersistedObj('settings', { modelId: undefined as string | undefined, + webSearchEnabled: false, }); diff --git a/src/routes/api/generate-message/+server.ts b/src/routes/api/generate-message/+server.ts index df5f77f..f1183be 100644 --- a/src/routes/api/generate-message/+server.ts +++ b/src/routes/api/generate-message/+server.ts @@ -21,6 +21,7 @@ const reqBodySchema = z.object({ session_token: z.string(), conversation_id: z.string().optional(), + web_search_enabled: z.boolean().optional(), images: z .array( z.object({ @@ -292,10 +293,16 @@ ${attachedRules.map((r) => `- ${r.name}: ${r.rule}`).join('\n')}`, return; } + // Check if web search is enabled for the last user message + const lastUserMessage = messages.filter(m => m.role === 'user').pop(); + const webSearchEnabled = lastUserMessage?.web_search_enabled ?? false; + + const modelId = webSearchEnabled ? `${model.model_id}:online` : model.model_id; + const streamResult = await ResultAsync.fromPromise( openai.chat.completions.create( { - model: model.model_id, + model: modelId, messages: messagesToSend, temperature: 0.7, stream: true, @@ -537,6 +544,7 @@ export const POST: RequestHandler = async ({ request }) => { content_html: '', role: 'user', images: args.images, + web_search_enabled: args.web_search_enabled, session_token: sessionToken, }), (e) => `Failed to create conversation: ${e}` @@ -572,6 +580,7 @@ export const POST: RequestHandler = async ({ request }) => { model_id: args.model_id, role: 'user', images: args.images, + web_search_enabled: args.web_search_enabled, }), (e) => `Failed to create user message: ${e}` ); diff --git a/src/routes/chat/+layout.svelte b/src/routes/chat/+layout.svelte index 070e1aa..01116cf 100644 --- a/src/routes/chat/+layout.svelte +++ b/src/routes/chat/+layout.svelte @@ -32,6 +32,7 @@ import Settings2Icon from '~icons/lucide/settings-2'; import UploadIcon from '~icons/lucide/upload'; import XIcon from '~icons/lucide/x'; + import SearchIcon from '~icons/lucide/search'; import { callGenerateMessage } from '../api/generate-message/call.js'; import { callCancelGeneration } from '../api/cancel-generation/call.js'; import ModelPicker from './model-picker.svelte'; @@ -97,6 +98,7 @@ conversation_id: page.params.id ?? undefined, model_id: settings.modelId, images: imagesCopy.length > 0 ? imagesCopy : undefined, + web_search_enabled: settings.webSearchEnabled, }); if (res.isErr()) { @@ -559,6 +561,17 @@
+ {#if currentModelSupportsImages}