diff --git a/package-lock.json b/package-lock.json index 87a3c59..e12c0bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@langchain/community": "^0.3.36", "@langchain/core": "^0.3.42", "@langchain/google-genai": "^0.1.12", + "@langchain/ollama": "0.2.0", "@langchain/openai": "^0.0.25", "@langchain/textsplitters": "^0.1.0", "@tailwindcss/typography": "^0.5.12", @@ -1989,6 +1990,37 @@ "@langchain/core": ">=0.3.17 <0.4.0" } }, + "node_modules/@langchain/ollama": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@langchain/ollama/-/ollama-0.2.0.tgz", + "integrity": "sha512-jLlYFqt+nbhaJKLakk7lRTWHZJ7wHeJLM6yuv4jToQ8zPzpL//372+MjggDoW0mnw8ofysg1T2C6mEJspKJtiA==", + "license": "MIT", + "dependencies": { + "ollama": "^0.5.12", + "uuid": "^10.0.0", + "zod": "^3.24.1", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.2.21 <0.4.0" + } + }, + "node_modules/@langchain/ollama/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@langchain/openai": { "version": "0.0.25", "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.0.25.tgz", @@ -8221,6 +8253,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ollama": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/ollama/-/ollama-0.5.15.tgz", + "integrity": "sha512-TSaZSJyP7MQJFjSmmNsoJiriwa3U+/UJRw6+M8aucs5dTsaWNZsBIGpDb5rXnW6nXxJBB/z79gZY8IaiIQgelQ==", + "license": "MIT", + "dependencies": { + "whatwg-fetch": "^3.6.20" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -10590,6 +10631,12 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -10965,12 +11012,12 @@ } }, "node_modules/zod-to-json-schema": { - "version": "3.23.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.1.tgz", - "integrity": "sha512-oT9INvydob1XV0v1d2IadrR74rLtDInLvDFfAa1CG0Pmg/vxATk7I2gSelfj271mbzeM4Da0uuDQE/Nkj3DWNw==", + "version": "3.24.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", + "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", "license": "ISC", "peerDependencies": { - "zod": "^3.23.3" + "zod": "^3.24.1" } } } diff --git a/package.json b/package.json index e68410f..bcff832 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@langchain/core": "^0.3.42", "@langchain/google-genai": "^0.1.12", "@langchain/openai": "^0.0.25", + "@langchain/ollama": "^0.2.0", "@langchain/textsplitters": "^0.1.0", "@tailwindcss/typography": "^0.5.12", "@xenova/transformers": "^2.17.2", diff --git a/src/app/api/chat/route.ts b/src/app/api/chat/route.ts index e566edb..5b87afb 100644 --- a/src/app/api/chat/route.ts +++ b/src/app/api/chat/route.ts @@ -20,6 +20,7 @@ import { getCustomOpenaiApiUrl, getCustomOpenaiModelName, } from '@/lib/config'; +import { ChatOllama } from '@langchain/ollama'; import { searchHandlers } from '@/lib/search'; export const runtime = 'nodejs'; @@ -34,6 +35,7 @@ type Message = { type ChatModel = { provider: string; name: string; + ollamaContextWindow?: number; }; type EmbeddingModel = { @@ -232,6 +234,11 @@ export const POST = async (req: Request) => { }) as unknown as BaseChatModel; } else if (chatModelProvider && chatModel) { llm = chatModel.model; + + // Set context window size for Ollama models + if (llm instanceof ChatOllama && body.chatModel?.provider === 'ollama') { + llm.numCtx = body.chatModel.ollamaContextWindow || 2048; + } } if (!llm) { diff --git a/src/app/api/search/route.ts b/src/app/api/search/route.ts index 970ec42..5d3cb5f 100644 --- a/src/app/api/search/route.ts +++ b/src/app/api/search/route.ts @@ -13,12 +13,14 @@ import { getCustomOpenaiModelName, } from '@/lib/config'; import { searchHandlers } from '@/lib/search'; +import { ChatOllama } from '@langchain/ollama'; interface chatModel { provider: string; name: string; customOpenAIKey?: string; customOpenAIBaseURL?: string; + ollamaContextWindow?: number; } interface embeddingModel { @@ -96,6 +98,10 @@ export const POST = async (req: Request) => { llm = chatModelProviders[chatModelProvider][chatModel] .model as unknown as BaseChatModel | undefined; } + + if (llm instanceof ChatOllama && body.chatModel?.provider === 'ollama') { + llm.numCtx = body.chatModel.ollamaContextWindow || 2048; + } if ( embeddingModelProviders[embeddingModelProvider] && diff --git a/src/app/api/suggestions/route.ts b/src/app/api/suggestions/route.ts index e92e5ec..63caff4 100644 --- a/src/app/api/suggestions/route.ts +++ b/src/app/api/suggestions/route.ts @@ -8,10 +8,12 @@ import { getAvailableChatModelProviders } from '@/lib/providers'; import { BaseChatModel } from '@langchain/core/language_models/chat_models'; import { AIMessage, BaseMessage, HumanMessage } from '@langchain/core/messages'; import { ChatOpenAI } from '@langchain/openai'; +import { ChatOllama } from '@langchain/ollama'; interface ChatModel { provider: string; model: string; + ollamaContextWindow?: number; } interface SuggestionsGenerationBody { @@ -57,6 +59,10 @@ export const POST = async (req: Request) => { }) as unknown as BaseChatModel; } else if (chatModelProvider && chatModel) { llm = chatModel.model; + // Set context window size for Ollama models + if (llm instanceof ChatOllama && body.chatModel?.provider === 'ollama') { + llm.numCtx = body.chatModel.ollamaContextWindow || 2048; + } } if (!llm) { diff --git a/src/components/ChatWindow.tsx b/src/components/ChatWindow.tsx index 9d776d2..61b55c1 100644 --- a/src/components/ChatWindow.tsx +++ b/src/components/ChatWindow.tsx @@ -494,6 +494,8 @@ const sendMessage = async ( } }; + const ollamaContextWindow = localStorage.getItem('ollamaContextWindow') || '2048'; + const res = await fetch('/api/chat', { method: 'POST', headers: { @@ -514,6 +516,9 @@ const sendMessage = async ( chatModel: { name: chatModelProvider.name, provider: chatModelProvider.provider, + ...(chatModelProvider.provider === 'ollama' && { + ollamaContextWindow: parseInt(ollamaContextWindow), + }), }, embeddingModel: { name: embeddingModelProvider.name, diff --git a/src/components/MessageInput.tsx b/src/components/MessageInput.tsx index 777141b..6c15814 100644 --- a/src/components/MessageInput.tsx +++ b/src/components/MessageInput.tsx @@ -80,49 +80,11 @@ const MessageInput = ({ }} className={cn( 'bg-light-secondary dark:bg-dark-secondary p-4 flex items-center border border-light-200 dark:border-dark-200', - mode === 'multi' ? 'flex-col rounded-lg' : 'flex-row rounded-full', + mode === 'multi' ? 'flex-col rounded-lg' : 'flex-col md:flex-row rounded-lg md:rounded-full', )} > {mode === 'single' && ( -
- - -
- )} - setMessage(e.target.value)} - onHeightChange={(height, props) => { - setTextareaRows(Math.ceil(height / props.rowHeight)); - }} - className="transition bg-transparent dark:placeholder:text-white/50 placeholder:text-sm text-sm dark:text-white resize-none focus:outline-none w-full px-2 max-h-24 lg:max-h-36 xl:max-h-48 flex-grow flex-shrink" - placeholder="Ask a follow-up" - /> - {mode === 'single' && ( -
- - -
- )} - {mode === 'multi' && ( -
+
-
+
+
+
+ )} +
+ setMessage(e.target.value)} + onHeightChange={(height, props) => { + setTextareaRows(Math.ceil(height / props.rowHeight)); + }} + className="transition bg-transparent dark:placeholder:text-white/50 placeholder:text-sm text-sm dark:text-white resize-none focus:outline-none w-full px-2 max-h-24 lg:max-h-36 xl:max-h-48 flex-grow flex-shrink" + placeholder="Ask a follow-up" + /> + {mode === 'single' && ( +
+
+ +
+
+ )} +
+ + {mode === 'multi' && ( +
+
+
+ + +
+
+ +
+
+
+
+ +
+ diff --git a/src/lib/providers/ollama.ts b/src/lib/providers/ollama.ts index cca2142..d5c7899 100644 --- a/src/lib/providers/ollama.ts +++ b/src/lib/providers/ollama.ts @@ -6,8 +6,8 @@ export const PROVIDER_INFO = { key: 'ollama', displayName: 'Ollama', }; -import { ChatOllama } from '@langchain/community/chat_models/ollama'; -import { OllamaEmbeddings } from '@langchain/community/embeddings/ollama'; +import { ChatOllama } from '@langchain/ollama'; +import { OllamaEmbeddings } from '@langchain/ollama'; export const loadOllamaChatModels = async () => { const ollamaApiEndpoint = getOllamaApiEndpoint(); diff --git a/src/lib/search/metaSearchAgent.ts b/src/lib/search/metaSearchAgent.ts index 9e05d48..d71ed8d 100644 --- a/src/lib/search/metaSearchAgent.ts +++ b/src/lib/search/metaSearchAgent.ts @@ -239,7 +239,6 @@ class MetaSearchAgent implements MetaSearchAgentType { optimizationMode: 'speed' | 'balanced' | 'quality', systemInstructions: string, ) { - console.log("optimization mode", optimizationMode); return RunnableSequence.from([ RunnableMap.from({ systemInstructions: () => systemInstructions, diff --git a/yarn.lock b/yarn.lock index 3e1d5bb..9c6f4fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -382,6 +382,16 @@ "@google/generative-ai" "^0.24.0" zod-to-json-schema "^3.22.4" +"@langchain/ollama@0.2.0": + version "0.2.0" + resolved "https://registry.npmjs.org/@langchain/ollama/-/ollama-0.2.0.tgz" + integrity sha512-jLlYFqt+nbhaJKLakk7lRTWHZJ7wHeJLM6yuv4jToQ8zPzpL//372+MjggDoW0mnw8ofysg1T2C6mEJspKJtiA== + dependencies: + ollama "^0.5.12" + uuid "^10.0.0" + zod "^3.24.1" + zod-to-json-schema "^3.24.1" + "@langchain/openai@^0.0.25", "@langchain/openai@~0.0.19": version "0.0.25" resolved "https://registry.npmjs.org/@langchain/openai/-/openai-0.0.25.tgz" @@ -3353,6 +3363,13 @@ object.values@^1.1.6, object.values@^1.2.0, object.values@^1.2.1: define-properties "^1.2.1" es-object-atoms "^1.0.0" +ollama@^0.5.12: + version "0.5.15" + resolved "https://registry.npmjs.org/ollama/-/ollama-0.5.15.tgz" + integrity sha512-TSaZSJyP7MQJFjSmmNsoJiriwa3U+/UJRw6+M8aucs5dTsaWNZsBIGpDb5rXnW6nXxJBB/z79gZY8IaiIQgelQ== + dependencies: + whatwg-fetch "^3.6.20" + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" @@ -4694,6 +4711,11 @@ webidl-conversions@^3.0.0: resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== +whatwg-fetch@^3.6.20: + version "3.6.20" + resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz" + integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" @@ -4838,10 +4860,10 @@ yocto-queue@^0.1.0: resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zod-to-json-schema@^3.22.3, zod-to-json-schema@^3.22.4, zod-to-json-schema@^3.22.5: - version "3.23.1" - resolved "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.1.tgz" - integrity sha512-oT9INvydob1XV0v1d2IadrR74rLtDInLvDFfAa1CG0Pmg/vxATk7I2gSelfj271mbzeM4Da0uuDQE/Nkj3DWNw== +zod-to-json-schema@^3.22.3, zod-to-json-schema@^3.22.4, zod-to-json-schema@^3.22.5, zod-to-json-schema@^3.24.1: + version "3.24.5" + resolved "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz" + integrity sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g== -zod@^3.22.3, zod@^3.22.4: +zod@^3.22.3, zod@^3.22.4, zod@^3.24.1: version "3.24.2"