mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-08 05:39:13 +00:00
Make it easier to manage server-level chat settings (#729)
* Add support for server-wide model settings fix web page reading results returning logic
This commit is contained in:
@@ -39,6 +39,7 @@ from khoj.database.models import (
|
|||||||
PublicConversation,
|
PublicConversation,
|
||||||
ReflectiveQuestion,
|
ReflectiveQuestion,
|
||||||
SearchModelConfig,
|
SearchModelConfig,
|
||||||
|
ServerChatSettings,
|
||||||
SpeechToTextModelOptions,
|
SpeechToTextModelOptions,
|
||||||
Subscription,
|
Subscription,
|
||||||
TextToImageModelConfig,
|
TextToImageModelConfig,
|
||||||
@@ -702,11 +703,36 @@ class ConversationAdapters:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_default_conversation_config():
|
def get_default_conversation_config():
|
||||||
|
server_chat_settings = ServerChatSettings.objects.first()
|
||||||
|
if server_chat_settings is None or server_chat_settings.default_model is None:
|
||||||
return ChatModelOptions.objects.filter().first()
|
return ChatModelOptions.objects.filter().first()
|
||||||
|
return server_chat_settings.default_model
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def aget_default_conversation_config():
|
async def aget_default_conversation_config():
|
||||||
|
server_chat_settings: ServerChatSettings = (
|
||||||
|
await ServerChatSettings.objects.filter()
|
||||||
|
.prefetch_related("default_model", "default_model__openai_config")
|
||||||
|
.afirst()
|
||||||
|
)
|
||||||
|
if server_chat_settings is None or server_chat_settings.default_model is None:
|
||||||
return await ChatModelOptions.objects.filter().prefetch_related("openai_config").afirst()
|
return await ChatModelOptions.objects.filter().prefetch_related("openai_config").afirst()
|
||||||
|
return server_chat_settings.default_model
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def aget_summarizer_conversation_config():
|
||||||
|
server_chat_settings: ServerChatSettings = (
|
||||||
|
await ServerChatSettings.objects.filter()
|
||||||
|
.prefetch_related(
|
||||||
|
"summarizer_model", "default_model", "default_model__openai_config", "summarizer_model__openai_config"
|
||||||
|
)
|
||||||
|
.afirst()
|
||||||
|
)
|
||||||
|
if server_chat_settings is None or (
|
||||||
|
server_chat_settings.summarizer_model is None and server_chat_settings.default_model is None
|
||||||
|
):
|
||||||
|
return await ChatModelOptions.objects.filter().afirst()
|
||||||
|
return server_chat_settings.summarizer_model or server_chat_settings.default_model
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_conversation_from_public_conversation(
|
def create_conversation_from_public_conversation(
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from khoj.database.models import (
|
|||||||
ProcessLock,
|
ProcessLock,
|
||||||
ReflectiveQuestion,
|
ReflectiveQuestion,
|
||||||
SearchModelConfig,
|
SearchModelConfig,
|
||||||
|
ServerChatSettings,
|
||||||
SpeechToTextModelOptions,
|
SpeechToTextModelOptions,
|
||||||
Subscription,
|
Subscription,
|
||||||
TextToImageModelConfig,
|
TextToImageModelConfig,
|
||||||
@@ -88,6 +89,7 @@ admin.site.register(TextToImageModelConfig)
|
|||||||
admin.site.register(ClientApplication)
|
admin.site.register(ClientApplication)
|
||||||
admin.site.register(GithubConfig)
|
admin.site.register(GithubConfig)
|
||||||
admin.site.register(NotionConfig)
|
admin.site.register(NotionConfig)
|
||||||
|
admin.site.register(ServerChatSettings)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Agent)
|
@admin.register(Agent)
|
||||||
|
|||||||
46
src/khoj/database/migrations/0042_serverchatsettings.py
Normal file
46
src/khoj/database/migrations/0042_serverchatsettings.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Generated by Django 4.2.10 on 2024-04-29 11:04
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("database", "0041_merge_20240505_1234"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="ServerChatSettings",
|
||||||
|
fields=[
|
||||||
|
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
("updated_at", models.DateTimeField(auto_now=True)),
|
||||||
|
(
|
||||||
|
"default_model",
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
default=None,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="default_model",
|
||||||
|
to="database.chatmodeloptions",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"summarizer_model",
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
default=None,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="summarizer_model",
|
||||||
|
to="database.chatmodeloptions",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"abstract": False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -158,6 +158,15 @@ class GithubRepoConfig(BaseModel):
|
|||||||
github_config = models.ForeignKey(GithubConfig, on_delete=models.CASCADE, related_name="githubrepoconfig")
|
github_config = models.ForeignKey(GithubConfig, on_delete=models.CASCADE, related_name="githubrepoconfig")
|
||||||
|
|
||||||
|
|
||||||
|
class ServerChatSettings(BaseModel):
|
||||||
|
default_model = models.ForeignKey(
|
||||||
|
ChatModelOptions, on_delete=models.CASCADE, default=None, null=True, blank=True, related_name="default_model"
|
||||||
|
)
|
||||||
|
summarizer_model = models.ForeignKey(
|
||||||
|
ChatModelOptions, on_delete=models.CASCADE, default=None, null=True, blank=True, related_name="summarizer_model"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LocalOrgConfig(BaseModel):
|
class LocalOrgConfig(BaseModel):
|
||||||
input_files = models.JSONField(default=list, null=True)
|
input_files = models.JSONField(default=list, null=True)
|
||||||
input_filter = models.JSONField(default=list, null=True)
|
input_filter = models.JSONField(default=list, null=True)
|
||||||
|
|||||||
@@ -613,11 +613,17 @@ async def websocket_endpoint(
|
|||||||
|
|
||||||
if ConversationCommand.Webpage in conversation_commands:
|
if ConversationCommand.Webpage in conversation_commands:
|
||||||
try:
|
try:
|
||||||
online_results = await read_webpages(defiltered_query, meta_log, location, send_status_update)
|
direct_web_pages = await read_webpages(defiltered_query, meta_log, location, send_status_update)
|
||||||
webpages = []
|
webpages = []
|
||||||
for query in online_results:
|
for query in direct_web_pages:
|
||||||
for webpage in online_results[query]["webpages"]:
|
if online_results.get(query):
|
||||||
|
online_results[query]["webpages"] = direct_web_pages[query]["webpages"]
|
||||||
|
else:
|
||||||
|
online_results[query] = {"webpages": direct_web_pages[query]["webpages"]}
|
||||||
|
|
||||||
|
for webpage in direct_web_pages[query]["webpages"]:
|
||||||
webpages.append(webpage["link"])
|
webpages.append(webpage["link"])
|
||||||
|
|
||||||
await send_status_update(f"**📚 Read web pages**: {webpages}")
|
await send_status_update(f"**📚 Read web pages**: {webpages}")
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
|||||||
@@ -392,9 +392,13 @@ async def extract_relevant_info(q: str, corpus: str) -> Union[str, None]:
|
|||||||
corpus=corpus.strip(),
|
corpus=corpus.strip(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
summarizer_model: ChatModelOptions = await ConversationAdapters.aget_summarizer_conversation_config()
|
||||||
|
|
||||||
with timer("Chat actor: Extract relevant information from data", logger):
|
with timer("Chat actor: Extract relevant information from data", logger):
|
||||||
response = await send_message_to_model_wrapper(
|
response = await send_message_to_model_wrapper(
|
||||||
extract_relevant_information, prompts.system_prompt_extract_relevant_information
|
extract_relevant_information,
|
||||||
|
prompts.system_prompt_extract_relevant_information,
|
||||||
|
chat_model_option=summarizer_model,
|
||||||
)
|
)
|
||||||
|
|
||||||
return response.strip()
|
return response.strip()
|
||||||
@@ -449,8 +453,11 @@ async def send_message_to_model_wrapper(
|
|||||||
message: str,
|
message: str,
|
||||||
system_message: str = "",
|
system_message: str = "",
|
||||||
response_type: str = "text",
|
response_type: str = "text",
|
||||||
|
chat_model_option: ChatModelOptions = None,
|
||||||
):
|
):
|
||||||
conversation_config: ChatModelOptions = await ConversationAdapters.aget_default_conversation_config()
|
conversation_config: ChatModelOptions = (
|
||||||
|
chat_model_option or await ConversationAdapters.aget_default_conversation_config()
|
||||||
|
)
|
||||||
|
|
||||||
if conversation_config is None:
|
if conversation_config is None:
|
||||||
raise HTTPException(status_code=500, detail="Contact the server administrator to set a default chat model.")
|
raise HTTPException(status_code=500, detail="Contact the server administrator to set a default chat model.")
|
||||||
|
|||||||
Reference in New Issue
Block a user