From 759873ec44a1cb69eebcf0831d64261e3b646966 Mon Sep 17 00:00:00 2001 From: sabaimran Date: Fri, 15 Nov 2024 15:22:06 -0800 Subject: [PATCH 01/11] Add documentation for how to use the text to image model configs --- .../docs/features/image_generation.md | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/documentation/docs/features/image_generation.md b/documentation/docs/features/image_generation.md index da6af1ac..df8d743f 100644 --- a/documentation/docs/features/image_generation.md +++ b/documentation/docs/features/image_generation.md @@ -10,6 +10,20 @@ To generate images, you just need to provide a prompt to Khoj in which the image ## Setup (Self-Hosting) -Right now, we only support integration with OpenAI's DALL-E. You need to have an OpenAI API key to use this feature. Here's how you can set it up: -1. Setup your OpenAI API key. See instructions [here](/get-started/setup#2-configure) -2. Create a text to image config at http://localhost:42110/server/admin/database/texttoimagemodelconfig/. We recommend the value `dall-e-3`. +You have a couple of image generation options. + +### OpenAI + +1. Get [an OpenAI API key](https://platform.openai.com/settings/organization/api-keys). +2. Setup your OpenAI API key, if you haven't already. See instructions [here](/get-started/setup#2-configure) +3. Create a text to image config at http://localhost:42110/server/admin/database/texttoimagemodelconfig/. We recommend the `model name` `dall-e-3`. Make sure to associate it with the OpenAI API chat configuration you setup in step 2 with `Openai config` field. + +### Flux + +1. You need a Replicate API key. You can find one [here](https://replicate.com/account/api-tokens). +1. Create a new [Text to Image Model](https://app.khoj.dev/server/admin/database/texttoimagemodelconfig/). Set the `type` to `Replicate`. We recommend the `model name` `black-forest-labs/flux-1.1-pro`. + +### Stable Diffusion + +1. Get an API key from [Stable Diffusion](https://www.stablediffusion.com/). +2. Create a new [Text to Image Model](https://app.khoj.dev/server/admin/database/texttoimagemodelconfig/). Set the `type` to `Stabilityai`. We recommend the `model name` `sd3-large`. From 15b4cec1e8c90b007e52c58dac2982f862aec68b Mon Sep 17 00:00:00 2001 From: sabaimran Date: Fri, 15 Nov 2024 15:26:14 -0800 Subject: [PATCH 02/11] Add documentation for how to use the text to image model configs, reduce to Replicate --- documentation/docs/features/image_generation.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/documentation/docs/features/image_generation.md b/documentation/docs/features/image_generation.md index df8d743f..14a005b3 100644 --- a/documentation/docs/features/image_generation.md +++ b/documentation/docs/features/image_generation.md @@ -12,18 +12,15 @@ To generate images, you just need to provide a prompt to Khoj in which the image You have a couple of image generation options. +### Image Generation Models + +We support most state of the art image generation models, including Ideogram, Flux, and Stable Diffusion. These will run using [Replicate](https://replicate.com). Here's how to set them up: + +1. Get a Replicate API key [here](https://replicate.com/account/api-tokens). +1. Create a new [Text to Image Model](https://app.khoj.dev/server/admin/database/texttoimagemodelconfig/). Set the `type` to `Replicate`. Use any of the model names you see [on this list](https://replicate.com/pricing#image-models). + ### OpenAI 1. Get [an OpenAI API key](https://platform.openai.com/settings/organization/api-keys). 2. Setup your OpenAI API key, if you haven't already. See instructions [here](/get-started/setup#2-configure) 3. Create a text to image config at http://localhost:42110/server/admin/database/texttoimagemodelconfig/. We recommend the `model name` `dall-e-3`. Make sure to associate it with the OpenAI API chat configuration you setup in step 2 with `Openai config` field. - -### Flux - -1. You need a Replicate API key. You can find one [here](https://replicate.com/account/api-tokens). -1. Create a new [Text to Image Model](https://app.khoj.dev/server/admin/database/texttoimagemodelconfig/). Set the `type` to `Replicate`. We recommend the `model name` `black-forest-labs/flux-1.1-pro`. - -### Stable Diffusion - -1. Get an API key from [Stable Diffusion](https://www.stablediffusion.com/). -2. Create a new [Text to Image Model](https://app.khoj.dev/server/admin/database/texttoimagemodelconfig/). Set the `type` to `Stabilityai`. We recommend the `model name` `sd3-large`. From a1b4587b34b93b240740091209161426265837a0 Mon Sep 17 00:00:00 2001 From: sabaimran Date: Fri, 15 Nov 2024 21:46:35 -0800 Subject: [PATCH 03/11] Remove extract_images flag from PDF loader --- src/khoj/processor/content/pdf/pdf_to_entries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/khoj/processor/content/pdf/pdf_to_entries.py b/src/khoj/processor/content/pdf/pdf_to_entries.py index 2b7122ea..f4856504 100644 --- a/src/khoj/processor/content/pdf/pdf_to_entries.py +++ b/src/khoj/processor/content/pdf/pdf_to_entries.py @@ -101,7 +101,7 @@ class PdfToEntries(TextToEntries): tmpf.flush() # Ensure all data is written # Load the content using PyMuPDFLoader - loader = PyMuPDFLoader(tmpf.name, extract_images=True) + loader = PyMuPDFLoader(tmpf.name) pdf_entries_per_file = loader.load() # Convert the loaded entries into the desired format From a16fc3ade8e307bbd7cc43b362c7069688f42f10 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Fri, 15 Nov 2024 01:25:13 -0800 Subject: [PATCH 04/11] Only add /research prefix when no slash command in message on web app - Explictly adding a slash command is a higher priority intent than research mode being enabled in the background. Respect that for a more intuitive UX flow. - Explicit slash commands do not currently work in research mode. You've to turn research mode off to use other slash commands. This is strange, unnecessary given intent priority is clear. --- .../web/app/components/chatInputArea/chatInputArea.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/interface/web/app/components/chatInputArea/chatInputArea.tsx b/src/interface/web/app/components/chatInputArea/chatInputArea.tsx index 74be1837..6bc19036 100644 --- a/src/interface/web/app/components/chatInputArea/chatInputArea.tsx +++ b/src/interface/web/app/components/chatInputArea/chatInputArea.tsx @@ -170,7 +170,12 @@ export const ChatInputArea = forwardRef((pr } let messageToSend = message.trim(); - if (useResearchMode && !messageToSend.startsWith("/research")) { + // Check if message starts with an explicit slash command + const startsWithSlashCommand = + props.chatOptionsData && + Object.keys(props.chatOptionsData).some((cmd) => messageToSend.startsWith(`/${cmd}`)); + // Only add /research if useResearchMode is enabled and message doesn't already use a slash command + if (useResearchMode && !startsWithSlashCommand) { messageToSend = `/research ${messageToSend}`; } From fc45aceecf585c870173a5a526a39c2bbe15ff6f Mon Sep 17 00:00:00 2001 From: Debanjum Date: Fri, 15 Nov 2024 01:57:23 -0800 Subject: [PATCH 05/11] Delete unused favicon ico in old web app directory --- .../web/assets/icons/favicon-128x128.ico | Bin 205167 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/khoj/interface/web/assets/icons/favicon-128x128.ico diff --git a/src/khoj/interface/web/assets/icons/favicon-128x128.ico b/src/khoj/interface/web/assets/icons/favicon-128x128.ico deleted file mode 100644 index ed751b2d14935cd7772f94fcde5b47e7a012a08d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205167 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

c%3v0@{AxLde#B?E#Do>UR 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 Date: Thu, 14 Nov 2024 15:49:41 -0800 Subject: [PATCH 06/11] Remove Talc search bench from Khoj eval script --- tests/eval_frames.py | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/tests/eval_frames.py b/tests/eval_frames.py index 9998d4c9..7788322d 100644 --- a/tests/eval_frames.py +++ b/tests/eval_frames.py @@ -48,38 +48,6 @@ def load_frames_dataset(): return None -def load_talc_dataset(): - """ - Load the TALC dataset from Github. - - Normalize it into the FRAMES benchmark structure and the HuggingFace Dataset format. - """ - try: - # Load TALC search benchmark from Github - raw_url = "https://raw.githubusercontent.com/Talc-AI/search-bench/3fd5b0858e2effa4c1578c7d046bee0a3895c488/data/searchbench_08_30_2024.jsonl" - response = requests.get(raw_url) - response.raise_for_status() - - # Parse benchmark from raw JSONL response - jsonl_data = [json.loads(line) for line in response.text.splitlines()] - - # Rename keys to match FRAMES format - formatted_data = [ - {"Prompt": d["question"], "Answer": d["expected_answer"], "reasoning_types": "talc"} for d in jsonl_data - ] - - # Convert benchmark to HF Dataset - dataset = Dataset.from_list(formatted_data) - dataset = dataset.shuffle() if RANDOMIZE else dataset - dataset = dataset.select(range(int(SAMPLE_SIZE))) if SAMPLE_SIZE else dataset - - return dataset - - except Exception as e: - logger.error(f"Error loading dataset: {e}") - return None - - def get_agent_response(prompt: str) -> str: """Get response from the Khoj API""" try: @@ -208,7 +176,7 @@ def parse_args(): "--dataset", "-d", default="frames", - choices=["frames", "talc"], + choices=["frames"], help="Dataset to use for evaluation (default: frames)", ) return parser.parse_args() @@ -223,8 +191,6 @@ def main(): with timer(f"Loaded {args.dataset} dataset in", logger): if args.dataset == "frames": dataset = load_frames_dataset() - elif args.dataset == "talc": - dataset = load_talc_dataset() if dataset is None: return From d9d58849581883675edb9bbe8815705d6468ea04 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Thu, 14 Nov 2024 15:55:00 -0800 Subject: [PATCH 07/11] Enable evaluating Khoj on the OpenAI SimpleQA bench using eval script - Just load the raw csv from OpenAI bucket. Normalize it into FRAMES format - Improve docstring for frames datasets as well - Log the load dataset perf timer at info level --- tests/eval_frames.py | 64 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/tests/eval_frames.py b/tests/eval_frames.py index 7788322d..8716e4d1 100644 --- a/tests/eval_frames.py +++ b/tests/eval_frames.py @@ -5,6 +5,7 @@ import logging import os import time from datetime import datetime +from io import StringIO from typing import Any, Dict import pandas as pd @@ -36,11 +37,21 @@ SLEEP_SECONDS = 1 # Delay between API calls to avoid rate limiting def load_frames_dataset(): - """Load the FRAMES benchmark dataset from HuggingFace""" + """ + Load the Google FRAMES benchmark dataset from HuggingFace + + FRAMES is a benchmark dataset to evaluate retrieval and answering capabilities of agents. + It contains ~800 requiring multi-hop retrieval and reasoning across various topics. + + ### Data Fields + - Prompt: The question to be answered + - Answer: The ground truth answer + - reasoning_types: The type of reasoning required to answer the question + """ try: dataset = load_dataset("google/frames-benchmark") - dataset = dataset.shuffle() if RANDOMIZE else dataset # Use test split for evaluation. Sample and shuffle dataset if configured + dataset = dataset.shuffle() if RANDOMIZE else dataset return dataset["test"][: int(SAMPLE_SIZE)] if SAMPLE_SIZE else dataset["test"] except Exception as e: @@ -48,6 +59,49 @@ def load_frames_dataset(): return None +def load_simpleqa_dataset(): + """ + Load the OpenAI SimpleQA benchmark dataset from their public bucket. + + SimpleQA is a dataset of moderately difficult q&a for 2024 models to answer across various topics. + It contains ~4000 human vetted questions and answers with additional metadata. + Its usage can be seen in openai/simple-evals github repository as well. + + ### Data Fields + - problem: The question to be answered + - answer: The ground truth answer + - metadata: Additional metadata including topic information + """ + + try: + # Load SimpleQA benchmark from OpenAI public bucket + raw_url = "https://openaipublic.blob.core.windows.net/simple-evals/simple_qa_test_set.csv" + response = requests.get(raw_url) + response.raise_for_status() + + # Parse benchmark from raw CSV response + csv_data = pd.read_csv(StringIO(response.text)) + # Normalize it into FRAMES format + formatted_data = [ + { + "Prompt": d["problem"], + "Answer": d["answer"], + "reasoning_types": json.loads(csv_data.to_dict("records")[0]["metadata"].replace("'", '"'))["topic"], + } + for d in csv_data.to_dict("records") + ] + + # Convert benchmark to HF Dataset + dataset = Dataset.from_list(formatted_data) + dataset = dataset.shuffle() if RANDOMIZE else dataset + dataset = dataset.select(range(int(SAMPLE_SIZE))) if SAMPLE_SIZE else dataset + + return dataset + except Exception as e: + logger.error(f"Error loading simpleqa dataset: {e}") + return None + + def get_agent_response(prompt: str) -> str: """Get response from the Khoj API""" try: @@ -176,7 +230,7 @@ def parse_args(): "--dataset", "-d", default="frames", - choices=["frames"], + choices=["frames", "simpleqa"], help="Dataset to use for evaluation (default: frames)", ) return parser.parse_args() @@ -188,9 +242,11 @@ def main(): dataset = None # Load dataset - with timer(f"Loaded {args.dataset} dataset in", logger): + with timer(f"Loaded {args.dataset} dataset in", logger, log_level=logging.INFO): if args.dataset == "frames": dataset = load_frames_dataset() + elif args.dataset == "simpleqa": + dataset = load_simpleqa_dataset() if dataset is None: return From 41d9011a26ce2f669739e7fafc9acf83a0f04cd4 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Fri, 15 Nov 2024 02:07:21 -0800 Subject: [PATCH 08/11] Move evaluation script into tests/evals directory This should give more space for eval scripts, results and readme --- tests/{eval_frames.py => evals/eval.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{eval_frames.py => evals/eval.py} (100%) diff --git a/tests/eval_frames.py b/tests/evals/eval.py similarity index 100% rename from tests/eval_frames.py rename to tests/evals/eval.py From 23ab258d7816190ac324174024ea10418ac26aee Mon Sep 17 00:00:00 2001 From: Debanjum Date: Fri, 15 Nov 2024 11:54:36 -0800 Subject: [PATCH 09/11] Improve user conversation config details on Admin panel Show user email and chat model that is associated with the user conversation config --- src/khoj/database/admin.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/khoj/database/admin.py b/src/khoj/database/admin.py index f7c140c1..d54e1579 100644 --- a/src/khoj/database/admin.py +++ b/src/khoj/database/admin.py @@ -108,7 +108,6 @@ admin.site.register(GithubConfig) admin.site.register(NotionConfig) admin.site.register(UserVoiceModelConfig) admin.site.register(VoiceModelOption) -admin.site.register(UserConversationConfig) admin.site.register(UserRequests) @@ -326,3 +325,35 @@ class ConversationAdmin(admin.ModelAdmin): if "export_selected_minimal_objects" in actions: del actions["export_selected_minimal_objects"] return actions + + +@admin.register(UserConversationConfig) +class UserConversationConfigAdmin(admin.ModelAdmin): + list_display = ( + "id", + "get_user_email", + "get_chat_model", + "get_subscription_type", + ) + search_fields = ("id", "user__email", "setting__chat_model", "user__subscription__type") + ordering = ("-updated_at",) + + def get_user_email(self, obj): + return obj.user.email + + get_user_email.short_description = "User Email" # type: ignore + get_user_email.admin_order_field = "user__email" # type: ignore + + def get_chat_model(self, obj): + return obj.setting.chat_model if obj.setting else None + + get_chat_model.short_description = "Chat Model" # type: ignore + get_chat_model.admin_order_field = "setting__chat_model" # type: ignore + + def get_subscription_type(self, obj): + if hasattr(obj.user, "subscription"): + return obj.user.subscription.type + return None + + get_subscription_type.short_description = "Subscription Type" # type: ignore + get_subscription_type.admin_order_field = "user__subscription__type" # type: ignore From 2366fa08b91d5655440f1fffd42b0d15e4e2be33 Mon Sep 17 00:00:00 2001 From: Debanjum Date: Sat, 16 Nov 2024 22:07:11 -0800 Subject: [PATCH 10/11] Update default vision supported & anthropic chat models on first run - Update to latest initialize with new claude 3.5 sonnet and haiku models - Update to set vision enabled for google and anthropic models by default. Previously we didn't support but we've supported this for a month or two now --- src/khoj/utils/constants.py | 2 +- src/khoj/utils/initialization.py | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/khoj/utils/constants.py b/src/khoj/utils/constants.py index d91cc84a..b8107edb 100644 --- a/src/khoj/utils/constants.py +++ b/src/khoj/utils/constants.py @@ -16,7 +16,7 @@ default_offline_chat_models = [ ] default_openai_chat_models = ["gpt-4o-mini", "gpt-4o"] default_gemini_chat_models = ["gemini-1.5-flash", "gemini-1.5-pro"] -default_anthropic_chat_models = ["claude-3-5-sonnet-20240620", "claude-3-opus-20240229"] +default_anthropic_chat_models = ["claude-3-5-sonnet-20241022", "claude-3-5-haiku-20241022"] empty_config = { "search-type": { diff --git a/src/khoj/utils/initialization.py b/src/khoj/utils/initialization.py index 6a39c41a..b8472288 100644 --- a/src/khoj/utils/initialization.py +++ b/src/khoj/utils/initialization.py @@ -87,7 +87,7 @@ def initialization(interactive: bool = True): ChatModelOptions.ModelType.GOOGLE, default_gemini_chat_models, default_api_key=os.getenv("GEMINI_API_KEY"), - vision_enabled=False, + vision_enabled=True, is_offline=False, interactive=interactive, provider_name="Google Gemini", @@ -98,7 +98,7 @@ def initialization(interactive: bool = True): ChatModelOptions.ModelType.ANTHROPIC, default_anthropic_chat_models, default_api_key=os.getenv("ANTHROPIC_API_KEY"), - vision_enabled=False, + vision_enabled=True, is_offline=False, interactive=interactive, ) @@ -158,7 +158,9 @@ def initialization(interactive: bool = True): is_offline: bool = False, provider_name: str = None, ) -> Tuple[bool, OpenAIProcessorConversationConfig]: - supported_vision_models = ["gpt-4o-mini", "gpt-4o"] + supported_vision_models = ( + default_openai_chat_models + default_anthropic_chat_models + default_gemini_chat_models + ) provider_name = provider_name or model_type.name.capitalize() default_use_model = {True: "y", False: "n"}[default_api_key is not None or is_offline] use_model_provider = ( From 69ef6829c1be23c3bdcf077fa8c7bb55177a080b Mon Sep 17 00:00:00 2001 From: Debanjum Date: Sat, 16 Nov 2024 23:53:11 -0800 Subject: [PATCH 11/11] Simplify integrating Ollama, OpenAI proxies with Khoj on first run - Integrate with Ollama or other openai compatible APIs by simply setting `OPENAI_API_BASE' environment variable in docker-compose etc. - Update docs on integrating with Ollama, openai proxies on first run - Auto populate all chat models supported by openai compatible APIs - Auto set vision enabled for all commercial models - Minor - Add huggingface cache to khoj_models volume. This is where chat models and (now) sentence transformer models are stored by default - Reduce verbosity of yarn install of web app. Otherwise hit docker log size limit & stops showing remaining logs after web app install - Suggest `ollama pull ` to start it in background --- Dockerfile | 2 +- docker-compose.yml | 8 ++- documentation/docs/advanced/ollama.md | 33 --------- documentation/docs/advanced/ollama.mdx | 78 ++++++++++++++++++++ documentation/docs/get-started/setup.mdx | 91 +++++++++++++----------- src/khoj/utils/initialization.py | 36 ++++++++-- 6 files changed, 164 insertions(+), 84 deletions(-) delete mode 100644 documentation/docs/advanced/ollama.md create mode 100644 documentation/docs/advanced/ollama.mdx diff --git a/Dockerfile b/Dockerfile index 73328c49..479fbadc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ENV PYTHONPATH=/app/src:$PYTHONPATH # Go to the directory src/interface/web and export the built Next.js assets WORKDIR /app/src/interface/web -RUN bash -c "yarn install --frozen-lockfile --verbose && yarn ciexport && yarn cache clean" +RUN bash -c "yarn install --frozen-lockfile && yarn ciexport && yarn cache clean" WORKDIR /app # Run the Application diff --git a/docker-compose.yml b/docker-compose.yml index ff2594f4..22b673e6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,6 +37,7 @@ services: volumes: - khoj_config:/root/.khoj/ - khoj_models:/root/.cache/torch/sentence_transformers + - khoj_models:/root/.cache/huggingface # Use 0.0.0.0 to explicitly set the host ip for the service on the container. https://pythonspeed.com/articles/docker-connection-refused/ environment: - POSTGRES_DB=postgres @@ -48,12 +49,17 @@ services: - KHOJ_DEBUG=False - KHOJ_ADMIN_EMAIL=username@example.com - KHOJ_ADMIN_PASSWORD=password - # Uncomment lines below to use chat models by each provider. + # Uncomment line below to use with Ollama running on your local machine at localhost:11434. + # Change URL to use with other OpenAI API compatible providers like VLLM, LMStudio etc. + # - OPENAI_API_BASE=http://host.docker.internal:11434/v1/ + # + # Uncomment appropriate lines below to use chat models by OpenAI, Anthropic, Google. # Ensure you set your provider specific API keys. # --- # - OPENAI_API_KEY=your_openai_api_key # - GEMINI_API_KEY=your_gemini_api_key # - ANTHROPIC_API_KEY=your_anthropic_api_key + # # Uncomment the necessary lines below to make your instance publicly accessible. # Replace the KHOJ_DOMAIN with either your domain or IP address (no http/https prefix). # Proceed with caution, especially if you are using anonymous mode. diff --git a/documentation/docs/advanced/ollama.md b/documentation/docs/advanced/ollama.md deleted file mode 100644 index 7e90f767..00000000 --- a/documentation/docs/advanced/ollama.md +++ /dev/null @@ -1,33 +0,0 @@ -# Ollama -:::info -This is only helpful for self-hosted users. If you're using [Khoj Cloud](https://app.khoj.dev), you're limited to our first-party models. -::: - -:::info -Khoj natively supports local LLMs [available on HuggingFace in GGUF format](https://huggingface.co/models?library=gguf). Using an OpenAI API proxy with Khoj maybe useful for ease of setup, trying new models or using commercial LLMs via API. -::: - -Ollama allows you to run [many popular open-source LLMs](https://ollama.com/library) locally from your terminal. -For folks comfortable with the terminal, Ollama's terminal based flows can ease setup and management of chat models. - -Ollama exposes a local [OpenAI API compatible server](https://github.com/ollama/ollama/blob/main/docs/openai.md#models). This makes it possible to use chat models from Ollama to create your personal AI agents with Khoj. - -## Setup - -1. Setup Ollama: https://ollama.com/ -2. Start your preferred model with Ollama. For example, - ```bash - ollama run llama3.1 - ``` -3. Create a new [OpenAI Processor Conversation Config](http://localhost:42110/server/admin/database/openaiprocessorconversationconfig/add) on your Khoj admin panel - - Name: `ollama` - - Api Key: `any string` - - Api Base Url: `http://localhost:11434/v1/` (default for Ollama) -4. Create a new [Chat Model Option](http://localhost:42110/server/admin/database/chatmodeloptions/add) on your Khoj admin panel. - - Name: `llama3.1` (replace with the name of your local model) - - Model Type: `Openai` - - Openai Config: `` - - Max prompt size: `20000` (replace with the max prompt size of your model) -5. Go to [your config](http://localhost:42110/settings) and select the model you just created in the chat model dropdown. - -That's it! You should now be able to chat with your Ollama model from Khoj. If you want to add additional models running on Ollama, repeat step 6 for each model. diff --git a/documentation/docs/advanced/ollama.mdx b/documentation/docs/advanced/ollama.mdx new file mode 100644 index 00000000..2557c7b4 --- /dev/null +++ b/documentation/docs/advanced/ollama.mdx @@ -0,0 +1,78 @@ +# Ollama + +```mdx-code-block +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +``` + +:::info +This is only helpful for self-hosted users. If you're using [Khoj Cloud](https://app.khoj.dev), you can use our first-party supported models. +::: + +:::info +Khoj can directly run local LLMs [available on HuggingFace in GGUF format](https://huggingface.co/models?library=gguf). The integration with Ollama is useful to run Khoj on Docker and have the chat models use your GPU or to try new models via CLI. +::: + +Ollama allows you to run [many popular open-source LLMs](https://ollama.com/library) locally from your terminal. +For folks comfortable with the terminal, Ollama's terminal based flows can ease setup and management of chat models. + +Ollama exposes a local [OpenAI API compatible server](https://github.com/ollama/ollama/blob/main/docs/openai.md#models). This makes it possible to use chat models from Ollama with Khoj. + +## Setup +:::info +Restart your Khoj server after first run or update to the settings below to ensure all settings are applied correctly. +::: + + + + + + 1. Setup Ollama: https://ollama.com/ + 2. Download your preferred chat model with Ollama. For example, + ```bash + ollama pull llama3.1 + ``` + 3. Uncomment `OPENAI_API_BASE` environment variable in your downloaded Khoj [docker-compose.yml](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml#:~:text=OPENAI_API_BASE) + 4. Start Khoj docker for the first time to automatically integrate and load models from the Ollama running on your host machine + ```bash + # run below command in the directory where you downloaded the Khoj docker-compose.yml + docker-compose up + ``` + + + + 1. Setup Ollama: https://ollama.com/ + 2. Download your preferred chat model with Ollama. For example, + ```bash + ollama pull llama3.1 + ``` + 3. Set `OPENAI_API_BASE` environment variable to `http://localhost:11434/v1` in your shell before starting Khoj for the first time + ```bash + export OPENAI_API_BASE="http://localhost:11434/v1" + khoj --anonymous-mode + ``` + + + + + 1. Setup Ollama: https://ollama.com/ + 2. Download your preferred chat model with Ollama. For example, + ```bash + ollama pull llama3.1 + ``` + 3. Create a new [OpenAI Processor Conversation Config](http://localhost:42110/server/admin/database/openaiprocessorconversationconfig/add) on your Khoj admin panel + - Name: `ollama` + - Api Key: `any string` + - Api Base Url: `http://localhost:11434/v1/` (default for Ollama) + 4. Create a new [Chat Model Option](http://localhost:42110/server/admin/database/chatmodeloptions/add) on your Khoj admin panel. + - Name: `llama3.1` (replace with the name of your local model) + - Model Type: `Openai` + - Openai Config: `` + - Max prompt size: `20000` (replace with the max prompt size of your model) + 5. Go to [your config](http://localhost:42110/settings) and select the model you just created in the chat model dropdown. + + If you want to add additional models running on Ollama, repeat step 4 for each model. + + + +That's it! You should now be able to chat with your Ollama model from Khoj. diff --git a/documentation/docs/get-started/setup.mdx b/documentation/docs/get-started/setup.mdx index 04146d9f..a7459376 100644 --- a/documentation/docs/get-started/setup.mdx +++ b/documentation/docs/get-started/setup.mdx @@ -19,7 +19,11 @@ These are the general setup instructions for self-hosted Khoj. You can install the Khoj server using either [Docker](?server=docker) or [Pip](?server=pip). :::info[Offline Model + GPU] -If you want to use the offline chat model and you have a GPU, you should use Installation Option 2 - local setup via the Python package directly. Our Docker image doesn't currently support running the offline chat model on GPU, making inference times really slow. +To use the offline chat model with your GPU, we recommend using the Docker setup with Ollama . You can also use the local Khoj setup via the Python package directly. +::: + +:::info[First Run] +Restart your Khoj server after the first run to ensure all settings are applied correctly. ::: @@ -28,27 +32,28 @@ If you want to use the offline chat model and you have a GPU, you should use Ins

Prerequisites

Docker

- (Option 1) Click here to install [Docker Desktop](https://docs.docker.com/desktop/install/mac-install/). Make sure you also install the [Docker Compose](https://docs.docker.com/desktop/install/mac-install/) tool. + - *Option 1*: Click here to install [Docker Desktop](https://docs.docker.com/desktop/install/mac-install/). Make sure you also install the [Docker Compose](https://docs.docker.com/desktop/install/mac-install/) tool. - (Option 2) Use [Homebrew](https://brew.sh/) to install Docker and Docker Compose. - ```shell - brew install --cask docker - brew install docker-compose - ``` + - *Option 2*: Use [Homebrew](https://brew.sh/) to install Docker and Docker Compose. + ```shell + brew install --cask docker + brew install docker-compose + ```

Setup

1. Download the Khoj docker-compose.yml file [from Github](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml) - ```shell - mkdir ~/.khoj && cd ~/.khoj - wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml - ``` - 2. Configure the environment variables in the docker-compose.yml - - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel. - - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini chat models respectively. + ```shell + mkdir ~/.khoj && cd ~/.khoj + wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml + ``` + 2. Configure the environment variables in the `docker-compose.yml` + - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel. + - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini commercial chat models respectively. + - Uncomment `OPENAI_API_BASE` to use [Ollama](/advanced/ollama?type=first-run&server=docker#setup) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio). 3. Start Khoj by running the following command in the same directory as your docker-compose.yml file. - ```shell - cd ~/.khoj - docker-compose up - ``` + ```shell + cd ~/.khoj + docker-compose up + ```

Prerequisites

@@ -61,20 +66,21 @@ If you want to use the offline chat model and you have a GPU, you should use Ins

Setup

1. Download the Khoj docker-compose.yml file [from Github](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml) - ```shell - # Windows users should use their WSL2 terminal to run these commands - mkdir ~/.khoj && cd ~/.khoj - wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml - ``` - 2. Configure the environment variables in the docker-compose.yml - - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel. - - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini chat models respectively. + ```shell + # Windows users should use their WSL2 terminal to run these commands + mkdir ~/.khoj && cd ~/.khoj + wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml + ``` + 2. Configure the environment variables in the `docker-compose.yml` + - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel. + - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini commercial chat models respectively. + - Uncomment `OPENAI_API_BASE` to use [Ollama](/advanced/ollama) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio). 3. Start Khoj by running the following command in the same directory as your docker-compose.yml file. - ```shell - # Windows users should use their WSL2 terminal to run these commands - cd ~/.khoj - docker-compose up - ``` + ```shell + # Windows users should use their WSL2 terminal to run these commands + cd ~/.khoj + docker-compose up + ```

Prerequisites

@@ -83,18 +89,19 @@ If you want to use the offline chat model and you have a GPU, you should use Ins

Setup

1. Download the Khoj docker-compose.yml file [from Github](https://github.com/khoj-ai/khoj/blob/master/docker-compose.yml) - ```shell - mkdir ~/.khoj && cd ~/.khoj - wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml - ``` - 2. Configure the environment variables in the docker-compose.yml - - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel. - - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini chat models respectively. + ```shell + mkdir ~/.khoj && cd ~/.khoj + wget https://raw.githubusercontent.com/khoj-ai/khoj/master/docker-compose.yml + ``` + 2. Configure the environment variables in the `docker-compose.yml` + - Set `KHOJ_ADMIN_PASSWORD`, `KHOJ_DJANGO_SECRET_KEY` (and optionally the `KHOJ_ADMIN_EMAIL`) to something secure. This allows you to customize Khoj later via the admin panel. + - Set `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` to your API key if you want to use OpenAI, Anthropic or Gemini commercial chat models respectively. + - Uncomment `OPENAI_API_BASE` to use [Ollama](/advanced/ollama) running on your host machine. Or set it to the URL of your OpenAI compatible API like vLLM or [LMStudio](/advanced/lmstudio). 3. Start Khoj by running the following command in the same directory as your docker-compose.yml file. - ```shell - cd ~/.khoj - docker-compose up - ``` + ```shell + cd ~/.khoj + docker-compose up + ```
diff --git a/src/khoj/utils/initialization.py b/src/khoj/utils/initialization.py index b8472288..53e73215 100644 --- a/src/khoj/utils/initialization.py +++ b/src/khoj/utils/initialization.py @@ -2,12 +2,13 @@ import logging import os from typing import Tuple +import openai + from khoj.database.adapters import ConversationAdapters from khoj.database.models import ( ChatModelOptions, KhojUser, OpenAIProcessorConversationConfig, - ServerChatSettings, SpeechToTextModelOptions, TextToImageModelConfig, ) @@ -42,14 +43,32 @@ def initialization(interactive: bool = True): "🗣️ Configure chat models available to your server. You can always update these at /server/admin using your admin account" ) + openai_api_base = os.getenv("OPENAI_API_BASE") + provider = "Ollama" if openai_api_base and openai_api_base.endswith(":11434/v1/") else "OpenAI" + openai_api_key = os.getenv("OPENAI_API_KEY", "placeholder" if openai_api_base else None) + default_chat_models = default_openai_chat_models + if openai_api_base: + # Get available chat models from OpenAI compatible API + try: + openai_client = openai.OpenAI(api_key=openai_api_key, base_url=openai_api_base) + default_chat_models = [model.id for model in openai_client.models.list()] + # Put the available default OpenAI models at the top + valid_default_models = [model for model in default_openai_chat_models if model in default_chat_models] + other_available_models = [model for model in default_chat_models if model not in valid_default_models] + default_chat_models = valid_default_models + other_available_models + except Exception: + logger.warning(f"⚠️ Failed to fetch {provider} chat models. Fallback to default models. Error: {e}") + # Set up OpenAI's online chat models openai_configured, openai_provider = _setup_chat_model_provider( ChatModelOptions.ModelType.OPENAI, - default_openai_chat_models, - default_api_key=os.getenv("OPENAI_API_KEY"), + default_chat_models, + default_api_key=openai_api_key, + api_base_url=openai_api_base, vision_enabled=True, is_offline=False, interactive=interactive, + provider_name=provider, ) # Setup OpenAI speech to text model @@ -154,6 +173,7 @@ def initialization(interactive: bool = True): default_chat_models: list, default_api_key: str, interactive: bool, + api_base_url: str = None, vision_enabled: bool = False, is_offline: bool = False, provider_name: str = None, @@ -172,14 +192,16 @@ def initialization(interactive: bool = True): logger.info(f"️💬 Setting up your {provider_name} chat configuration") - chat_model_provider = None + chat_provider = None if not is_offline: if interactive: user_api_key = input(f"Enter your {provider_name} API key (default: {default_api_key}): ") api_key = user_api_key if user_api_key != "" else default_api_key else: api_key = default_api_key - chat_model_provider = OpenAIProcessorConversationConfig.objects.create(api_key=api_key, name=provider_name) + chat_provider = OpenAIProcessorConversationConfig.objects.create( + api_key=api_key, name=provider_name, api_base_url=api_base_url + ) if interactive: chat_model_names = input( @@ -201,13 +223,13 @@ def initialization(interactive: bool = True): "max_prompt_size": default_max_tokens, "vision_enabled": vision_enabled, "tokenizer": default_tokenizer, - "openai_config": chat_model_provider, + "openai_config": chat_provider, } ChatModelOptions.objects.create(**chat_model_options) logger.info(f"🗣️ {provider_name} chat model configuration complete") - return True, chat_model_provider + return True, chat_provider admin_user = KhojUser.objects.filter(is_staff=True).first() if admin_user is None: