khoj 1.16.1.dev15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- khoj/__init__.py +0 -0
- khoj/app/README.md +94 -0
- khoj/app/__init__.py +0 -0
- khoj/app/asgi.py +16 -0
- khoj/app/settings.py +192 -0
- khoj/app/urls.py +25 -0
- khoj/configure.py +424 -0
- khoj/database/__init__.py +0 -0
- khoj/database/adapters/__init__.py +1234 -0
- khoj/database/admin.py +290 -0
- khoj/database/apps.py +6 -0
- khoj/database/management/__init__.py +0 -0
- khoj/database/management/commands/__init__.py +0 -0
- khoj/database/management/commands/change_generated_images_url.py +61 -0
- khoj/database/management/commands/convert_images_png_to_webp.py +99 -0
- khoj/database/migrations/0001_khojuser.py +98 -0
- khoj/database/migrations/0002_googleuser.py +32 -0
- khoj/database/migrations/0003_vector_extension.py +10 -0
- khoj/database/migrations/0004_content_types_and_more.py +181 -0
- khoj/database/migrations/0005_embeddings_corpus_id.py +19 -0
- khoj/database/migrations/0006_embeddingsdates.py +33 -0
- khoj/database/migrations/0007_add_conversation.py +27 -0
- khoj/database/migrations/0008_alter_conversation_conversation_log.py +17 -0
- khoj/database/migrations/0009_khojapiuser.py +24 -0
- khoj/database/migrations/0010_chatmodeloptions_and_more.py +83 -0
- khoj/database/migrations/0010_rename_embeddings_entry_and_more.py +30 -0
- khoj/database/migrations/0011_merge_20231102_0138.py +14 -0
- khoj/database/migrations/0012_entry_file_source.py +21 -0
- khoj/database/migrations/0013_subscription.py +37 -0
- khoj/database/migrations/0014_alter_googleuser_picture.py +17 -0
- khoj/database/migrations/0015_alter_subscription_user.py +21 -0
- khoj/database/migrations/0016_alter_subscription_renewal_date.py +17 -0
- khoj/database/migrations/0017_searchmodel.py +32 -0
- khoj/database/migrations/0018_searchmodelconfig_delete_searchmodel.py +30 -0
- khoj/database/migrations/0019_alter_googleuser_family_name_and_more.py +27 -0
- khoj/database/migrations/0020_reflectivequestion.py +36 -0
- khoj/database/migrations/0021_speechtotextmodeloptions_and_more.py +42 -0
- khoj/database/migrations/0022_texttoimagemodelconfig.py +25 -0
- khoj/database/migrations/0023_usersearchmodelconfig.py +33 -0
- khoj/database/migrations/0024_alter_entry_embeddings.py +18 -0
- khoj/database/migrations/0025_clientapplication_khojuser_phone_number_and_more.py +46 -0
- khoj/database/migrations/0025_searchmodelconfig_embeddings_inference_endpoint_and_more.py +22 -0
- khoj/database/migrations/0026_searchmodelconfig_cross_encoder_inference_endpoint_and_more.py +22 -0
- khoj/database/migrations/0027_merge_20240118_1324.py +13 -0
- khoj/database/migrations/0028_khojuser_verified_phone_number.py +17 -0
- khoj/database/migrations/0029_userrequests.py +27 -0
- khoj/database/migrations/0030_conversation_slug_and_title.py +38 -0
- khoj/database/migrations/0031_agent_conversation_agent.py +53 -0
- khoj/database/migrations/0031_alter_googleuser_locale.py +30 -0
- khoj/database/migrations/0032_merge_20240322_0427.py +14 -0
- khoj/database/migrations/0033_rename_tuning_agent_personality.py +17 -0
- khoj/database/migrations/0034_alter_chatmodeloptions_chat_model.py +32 -0
- khoj/database/migrations/0035_processlock.py +26 -0
- khoj/database/migrations/0036_alter_processlock_name.py +19 -0
- khoj/database/migrations/0036_delete_offlinechatprocessorconversationconfig.py +15 -0
- khoj/database/migrations/0036_publicconversation.py +42 -0
- khoj/database/migrations/0037_chatmodeloptions_openai_config_and_more.py +51 -0
- khoj/database/migrations/0037_searchmodelconfig_bi_encoder_docs_encode_config_and_more.py +32 -0
- khoj/database/migrations/0038_merge_20240425_0857.py +14 -0
- khoj/database/migrations/0038_merge_20240426_1640.py +12 -0
- khoj/database/migrations/0039_merge_20240501_0301.py +12 -0
- khoj/database/migrations/0040_alter_processlock_name.py +26 -0
- khoj/database/migrations/0040_merge_20240504_1010.py +14 -0
- khoj/database/migrations/0041_merge_20240505_1234.py +14 -0
- khoj/database/migrations/0042_serverchatsettings.py +46 -0
- khoj/database/migrations/0043_alter_chatmodeloptions_model_type.py +21 -0
- khoj/database/migrations/0044_conversation_file_filters.py +17 -0
- khoj/database/migrations/0045_fileobject.py +37 -0
- khoj/database/migrations/0046_khojuser_email_verification_code_and_more.py +22 -0
- khoj/database/migrations/0047_alter_entry_file_type.py +31 -0
- khoj/database/migrations/0048_voicemodeloption_uservoicemodelconfig.py +52 -0
- khoj/database/migrations/0049_datastore.py +38 -0
- khoj/database/migrations/0049_texttoimagemodelconfig_api_key_and_more.py +58 -0
- khoj/database/migrations/0050_alter_processlock_name.py +25 -0
- khoj/database/migrations/0051_merge_20240702_1220.py +14 -0
- khoj/database/migrations/0052_alter_searchmodelconfig_bi_encoder_docs_encode_config_and_more.py +27 -0
- khoj/database/migrations/__init__.py +0 -0
- khoj/database/models/__init__.py +402 -0
- khoj/database/tests.py +3 -0
- khoj/interface/email/feedback.html +34 -0
- khoj/interface/email/magic_link.html +17 -0
- khoj/interface/email/task.html +40 -0
- khoj/interface/email/welcome.html +61 -0
- khoj/interface/web/404.html +56 -0
- khoj/interface/web/agent.html +312 -0
- khoj/interface/web/agents.html +276 -0
- khoj/interface/web/assets/icons/agents.svg +6 -0
- khoj/interface/web/assets/icons/automation.svg +37 -0
- khoj/interface/web/assets/icons/cancel.svg +3 -0
- khoj/interface/web/assets/icons/chat.svg +24 -0
- khoj/interface/web/assets/icons/collapse.svg +17 -0
- khoj/interface/web/assets/icons/computer.png +0 -0
- khoj/interface/web/assets/icons/confirm-icon.svg +1 -0
- khoj/interface/web/assets/icons/copy-button-success.svg +6 -0
- khoj/interface/web/assets/icons/copy-button.svg +5 -0
- khoj/interface/web/assets/icons/credit-card.png +0 -0
- khoj/interface/web/assets/icons/delete.svg +26 -0
- khoj/interface/web/assets/icons/docx.svg +7 -0
- khoj/interface/web/assets/icons/edit.svg +4 -0
- khoj/interface/web/assets/icons/favicon-128x128.ico +0 -0
- khoj/interface/web/assets/icons/favicon-128x128.png +0 -0
- khoj/interface/web/assets/icons/favicon-256x256.png +0 -0
- khoj/interface/web/assets/icons/favicon.icns +0 -0
- khoj/interface/web/assets/icons/github.svg +1 -0
- khoj/interface/web/assets/icons/key.svg +4 -0
- khoj/interface/web/assets/icons/khoj-logo-sideways-200.png +0 -0
- khoj/interface/web/assets/icons/khoj-logo-sideways-500.png +0 -0
- khoj/interface/web/assets/icons/khoj-logo-sideways.svg +5385 -0
- khoj/interface/web/assets/icons/logotype.svg +1 -0
- khoj/interface/web/assets/icons/markdown.svg +1 -0
- khoj/interface/web/assets/icons/new.svg +23 -0
- khoj/interface/web/assets/icons/notion.svg +4 -0
- khoj/interface/web/assets/icons/openai-logomark.svg +1 -0
- khoj/interface/web/assets/icons/org.svg +1 -0
- khoj/interface/web/assets/icons/pdf.svg +23 -0
- khoj/interface/web/assets/icons/pencil-edit.svg +5 -0
- khoj/interface/web/assets/icons/plaintext.svg +1 -0
- khoj/interface/web/assets/icons/question-mark-icon.svg +1 -0
- khoj/interface/web/assets/icons/search.svg +25 -0
- khoj/interface/web/assets/icons/send.svg +1 -0
- khoj/interface/web/assets/icons/share.svg +8 -0
- khoj/interface/web/assets/icons/speaker.svg +4 -0
- khoj/interface/web/assets/icons/stop-solid.svg +37 -0
- khoj/interface/web/assets/icons/sync.svg +4 -0
- khoj/interface/web/assets/icons/thumbs-down-svgrepo-com.svg +6 -0
- khoj/interface/web/assets/icons/thumbs-up-svgrepo-com.svg +6 -0
- khoj/interface/web/assets/icons/user-silhouette.svg +4 -0
- khoj/interface/web/assets/icons/voice.svg +8 -0
- khoj/interface/web/assets/icons/web.svg +2 -0
- khoj/interface/web/assets/icons/whatsapp.svg +17 -0
- khoj/interface/web/assets/khoj.css +237 -0
- khoj/interface/web/assets/markdown-it.min.js +8476 -0
- khoj/interface/web/assets/natural-cron.min.js +1 -0
- khoj/interface/web/assets/org.min.js +1823 -0
- khoj/interface/web/assets/pico.min.css +5 -0
- khoj/interface/web/assets/purify.min.js +3 -0
- khoj/interface/web/assets/samples/desktop-browse-draw-sample.png +0 -0
- khoj/interface/web/assets/samples/desktop-plain-chat-sample.png +0 -0
- khoj/interface/web/assets/samples/desktop-remember-plan-sample.png +0 -0
- khoj/interface/web/assets/samples/phone-browse-draw-sample.png +0 -0
- khoj/interface/web/assets/samples/phone-plain-chat-sample.png +0 -0
- khoj/interface/web/assets/samples/phone-remember-plan-sample.png +0 -0
- khoj/interface/web/assets/utils.js +33 -0
- khoj/interface/web/base_config.html +445 -0
- khoj/interface/web/chat.html +3546 -0
- khoj/interface/web/config.html +1011 -0
- khoj/interface/web/config_automation.html +1103 -0
- khoj/interface/web/content_source_computer_input.html +139 -0
- khoj/interface/web/content_source_github_input.html +216 -0
- khoj/interface/web/content_source_notion_input.html +94 -0
- khoj/interface/web/khoj.webmanifest +51 -0
- khoj/interface/web/login.html +219 -0
- khoj/interface/web/public_conversation.html +2006 -0
- khoj/interface/web/search.html +470 -0
- khoj/interface/web/utils.html +48 -0
- khoj/main.py +241 -0
- khoj/manage.py +22 -0
- khoj/migrations/__init__.py +0 -0
- khoj/migrations/migrate_offline_chat_default_model.py +69 -0
- khoj/migrations/migrate_offline_chat_default_model_2.py +71 -0
- khoj/migrations/migrate_offline_chat_schema.py +83 -0
- khoj/migrations/migrate_offline_model.py +29 -0
- khoj/migrations/migrate_processor_config_openai.py +67 -0
- khoj/migrations/migrate_server_pg.py +138 -0
- khoj/migrations/migrate_version.py +17 -0
- khoj/processor/__init__.py +0 -0
- khoj/processor/content/__init__.py +0 -0
- khoj/processor/content/docx/__init__.py +0 -0
- khoj/processor/content/docx/docx_to_entries.py +110 -0
- khoj/processor/content/github/__init__.py +0 -0
- khoj/processor/content/github/github_to_entries.py +224 -0
- khoj/processor/content/images/__init__.py +0 -0
- khoj/processor/content/images/image_to_entries.py +118 -0
- khoj/processor/content/markdown/__init__.py +0 -0
- khoj/processor/content/markdown/markdown_to_entries.py +165 -0
- khoj/processor/content/notion/notion_to_entries.py +260 -0
- khoj/processor/content/org_mode/__init__.py +0 -0
- khoj/processor/content/org_mode/org_to_entries.py +231 -0
- khoj/processor/content/org_mode/orgnode.py +532 -0
- khoj/processor/content/pdf/__init__.py +0 -0
- khoj/processor/content/pdf/pdf_to_entries.py +116 -0
- khoj/processor/content/plaintext/__init__.py +0 -0
- khoj/processor/content/plaintext/plaintext_to_entries.py +122 -0
- khoj/processor/content/text_to_entries.py +297 -0
- khoj/processor/conversation/__init__.py +0 -0
- khoj/processor/conversation/anthropic/__init__.py +0 -0
- khoj/processor/conversation/anthropic/anthropic_chat.py +206 -0
- khoj/processor/conversation/anthropic/utils.py +114 -0
- khoj/processor/conversation/offline/__init__.py +0 -0
- khoj/processor/conversation/offline/chat_model.py +231 -0
- khoj/processor/conversation/offline/utils.py +78 -0
- khoj/processor/conversation/offline/whisper.py +15 -0
- khoj/processor/conversation/openai/__init__.py +0 -0
- khoj/processor/conversation/openai/gpt.py +187 -0
- khoj/processor/conversation/openai/utils.py +129 -0
- khoj/processor/conversation/openai/whisper.py +13 -0
- khoj/processor/conversation/prompts.py +758 -0
- khoj/processor/conversation/utils.py +262 -0
- khoj/processor/embeddings.py +117 -0
- khoj/processor/speech/__init__.py +0 -0
- khoj/processor/speech/text_to_speech.py +51 -0
- khoj/processor/tools/__init__.py +0 -0
- khoj/processor/tools/online_search.py +225 -0
- khoj/routers/__init__.py +0 -0
- khoj/routers/api.py +626 -0
- khoj/routers/api_agents.py +43 -0
- khoj/routers/api_chat.py +1180 -0
- khoj/routers/api_config.py +434 -0
- khoj/routers/api_phone.py +86 -0
- khoj/routers/auth.py +181 -0
- khoj/routers/email.py +133 -0
- khoj/routers/helpers.py +1188 -0
- khoj/routers/indexer.py +349 -0
- khoj/routers/notion.py +91 -0
- khoj/routers/storage.py +35 -0
- khoj/routers/subscription.py +104 -0
- khoj/routers/twilio.py +36 -0
- khoj/routers/web_client.py +471 -0
- khoj/search_filter/__init__.py +0 -0
- khoj/search_filter/base_filter.py +15 -0
- khoj/search_filter/date_filter.py +217 -0
- khoj/search_filter/file_filter.py +30 -0
- khoj/search_filter/word_filter.py +29 -0
- khoj/search_type/__init__.py +0 -0
- khoj/search_type/text_search.py +241 -0
- khoj/utils/__init__.py +0 -0
- khoj/utils/cli.py +93 -0
- khoj/utils/config.py +81 -0
- khoj/utils/constants.py +24 -0
- khoj/utils/fs_syncer.py +249 -0
- khoj/utils/helpers.py +418 -0
- khoj/utils/initialization.py +146 -0
- khoj/utils/jsonl.py +43 -0
- khoj/utils/models.py +47 -0
- khoj/utils/rawconfig.py +160 -0
- khoj/utils/state.py +46 -0
- khoj/utils/yaml.py +43 -0
- khoj-1.16.1.dev15.dist-info/METADATA +178 -0
- khoj-1.16.1.dev15.dist-info/RECORD +242 -0
- khoj-1.16.1.dev15.dist-info/WHEEL +4 -0
- khoj-1.16.1.dev15.dist-info/entry_points.txt +2 -0
- khoj-1.16.1.dev15.dist-info/licenses/LICENSE +661 -0
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import uuid
|
|
3
|
+
from random import choice
|
|
4
|
+
|
|
5
|
+
from django.contrib.auth.models import AbstractUser
|
|
6
|
+
from django.core.exceptions import ValidationError
|
|
7
|
+
from django.db import models
|
|
8
|
+
from django.db.models.signals import pre_save
|
|
9
|
+
from django.dispatch import receiver
|
|
10
|
+
from pgvector.django import VectorField
|
|
11
|
+
from phonenumber_field.modelfields import PhoneNumberField
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BaseModel(models.Model):
|
|
15
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
16
|
+
updated_at = models.DateTimeField(auto_now=True)
|
|
17
|
+
|
|
18
|
+
class Meta:
|
|
19
|
+
abstract = True
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ClientApplication(BaseModel):
|
|
23
|
+
name = models.CharField(max_length=200)
|
|
24
|
+
client_id = models.CharField(max_length=200)
|
|
25
|
+
client_secret = models.CharField(max_length=200)
|
|
26
|
+
|
|
27
|
+
def __str__(self):
|
|
28
|
+
return self.name
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class KhojUser(AbstractUser):
|
|
32
|
+
uuid = models.UUIDField(models.UUIDField(default=uuid.uuid4, editable=False))
|
|
33
|
+
phone_number = PhoneNumberField(null=True, default=None, blank=True)
|
|
34
|
+
verified_phone_number = models.BooleanField(default=False)
|
|
35
|
+
verified_email = models.BooleanField(default=False)
|
|
36
|
+
email_verification_code = models.CharField(max_length=200, null=True, default=None, blank=True)
|
|
37
|
+
|
|
38
|
+
def save(self, *args, **kwargs):
|
|
39
|
+
if not self.uuid:
|
|
40
|
+
self.uuid = uuid.uuid4()
|
|
41
|
+
super().save(*args, **kwargs)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class GoogleUser(models.Model):
|
|
45
|
+
user = models.OneToOneField(KhojUser, on_delete=models.CASCADE)
|
|
46
|
+
sub = models.CharField(max_length=200)
|
|
47
|
+
azp = models.CharField(max_length=200)
|
|
48
|
+
email = models.CharField(max_length=200)
|
|
49
|
+
name = models.CharField(max_length=200, null=True, default=None, blank=True)
|
|
50
|
+
given_name = models.CharField(max_length=200, null=True, default=None, blank=True)
|
|
51
|
+
family_name = models.CharField(max_length=200, null=True, default=None, blank=True)
|
|
52
|
+
picture = models.CharField(max_length=200, null=True, default=None)
|
|
53
|
+
locale = models.CharField(max_length=200, null=True, default=None, blank=True)
|
|
54
|
+
|
|
55
|
+
def __str__(self):
|
|
56
|
+
return self.name
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class KhojApiUser(models.Model):
|
|
60
|
+
"""User issued API tokens to authenticate Khoj clients"""
|
|
61
|
+
|
|
62
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
63
|
+
token = models.CharField(max_length=50, unique=True)
|
|
64
|
+
name = models.CharField(max_length=50)
|
|
65
|
+
accessed_at = models.DateTimeField(null=True, default=None)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Subscription(BaseModel):
|
|
69
|
+
class Type(models.TextChoices):
|
|
70
|
+
TRIAL = "trial"
|
|
71
|
+
STANDARD = "standard"
|
|
72
|
+
|
|
73
|
+
user = models.OneToOneField(KhojUser, on_delete=models.CASCADE, related_name="subscription")
|
|
74
|
+
type = models.CharField(max_length=20, choices=Type.choices, default=Type.TRIAL)
|
|
75
|
+
is_recurring = models.BooleanField(default=False)
|
|
76
|
+
renewal_date = models.DateTimeField(null=True, default=None, blank=True)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class OpenAIProcessorConversationConfig(BaseModel):
|
|
80
|
+
name = models.CharField(max_length=200)
|
|
81
|
+
api_key = models.CharField(max_length=200)
|
|
82
|
+
api_base_url = models.URLField(max_length=200, default=None, blank=True, null=True)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class ChatModelOptions(BaseModel):
|
|
86
|
+
class ModelType(models.TextChoices):
|
|
87
|
+
OPENAI = "openai"
|
|
88
|
+
OFFLINE = "offline"
|
|
89
|
+
ANTHROPIC = "anthropic"
|
|
90
|
+
|
|
91
|
+
max_prompt_size = models.IntegerField(default=None, null=True, blank=True)
|
|
92
|
+
tokenizer = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
93
|
+
chat_model = models.CharField(max_length=200, default="NousResearch/Hermes-2-Pro-Mistral-7B-GGUF")
|
|
94
|
+
model_type = models.CharField(max_length=200, choices=ModelType.choices, default=ModelType.OFFLINE)
|
|
95
|
+
openai_config = models.ForeignKey(
|
|
96
|
+
OpenAIProcessorConversationConfig, on_delete=models.CASCADE, default=None, null=True, blank=True
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class VoiceModelOption(BaseModel):
|
|
101
|
+
model_id = models.CharField(max_length=200)
|
|
102
|
+
name = models.CharField(max_length=200)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class Agent(BaseModel):
|
|
106
|
+
creator = models.ForeignKey(
|
|
107
|
+
KhojUser, on_delete=models.CASCADE, default=None, null=True, blank=True
|
|
108
|
+
) # Creator will only be null when the agents are managed by admin
|
|
109
|
+
name = models.CharField(max_length=200)
|
|
110
|
+
personality = models.TextField()
|
|
111
|
+
avatar = models.URLField(max_length=400, default=None, null=True, blank=True)
|
|
112
|
+
tools = models.JSONField(default=list) # List of tools the agent has access to, like online search or notes search
|
|
113
|
+
public = models.BooleanField(default=False)
|
|
114
|
+
managed_by_admin = models.BooleanField(default=False)
|
|
115
|
+
chat_model = models.ForeignKey(ChatModelOptions, on_delete=models.CASCADE)
|
|
116
|
+
slug = models.CharField(max_length=200)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class ProcessLock(BaseModel):
|
|
120
|
+
class Operation(models.TextChoices):
|
|
121
|
+
INDEX_CONTENT = "index_content"
|
|
122
|
+
SCHEDULED_JOB = "scheduled_job"
|
|
123
|
+
SCHEDULE_LEADER = "schedule_leader"
|
|
124
|
+
|
|
125
|
+
# We need to make sure that some operations are thread-safe. To do so, add locks for potentially shared operations.
|
|
126
|
+
# For example, we need to make sure that only one process is updating the embeddings at a time.
|
|
127
|
+
name = models.CharField(max_length=200, choices=Operation.choices, unique=True)
|
|
128
|
+
started_at = models.DateTimeField(auto_now_add=True)
|
|
129
|
+
max_duration_in_seconds = models.IntegerField(default=60 * 60 * 12) # 12 hours
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@receiver(pre_save, sender=Agent)
|
|
133
|
+
def verify_agent(sender, instance, **kwargs):
|
|
134
|
+
# check if this is a new instance
|
|
135
|
+
if instance._state.adding:
|
|
136
|
+
if Agent.objects.filter(name=instance.name, public=True).exists():
|
|
137
|
+
raise ValidationError(f"A public Agent with the name {instance.name} already exists.")
|
|
138
|
+
if Agent.objects.filter(name=instance.name, creator=instance.creator).exists():
|
|
139
|
+
raise ValidationError(f"A private Agent with the name {instance.name} already exists.")
|
|
140
|
+
|
|
141
|
+
slug = instance.name.lower().replace(" ", "-")
|
|
142
|
+
observed_random_numbers = set()
|
|
143
|
+
while Agent.objects.filter(slug=slug).exists():
|
|
144
|
+
try:
|
|
145
|
+
random_number = choice([i for i in range(0, 1000) if i not in observed_random_numbers])
|
|
146
|
+
except IndexError:
|
|
147
|
+
raise ValidationError("Unable to generate a unique slug for the Agent. Please try again later.")
|
|
148
|
+
observed_random_numbers.add(random_number)
|
|
149
|
+
slug = f"{slug}-{random_number}"
|
|
150
|
+
instance.slug = slug
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class NotionConfig(BaseModel):
|
|
154
|
+
token = models.CharField(max_length=200)
|
|
155
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class GithubConfig(BaseModel):
|
|
159
|
+
pat_token = models.CharField(max_length=200)
|
|
160
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class GithubRepoConfig(BaseModel):
|
|
164
|
+
name = models.CharField(max_length=200)
|
|
165
|
+
owner = models.CharField(max_length=200)
|
|
166
|
+
branch = models.CharField(max_length=200)
|
|
167
|
+
github_config = models.ForeignKey(GithubConfig, on_delete=models.CASCADE, related_name="githubrepoconfig")
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class ServerChatSettings(BaseModel):
|
|
171
|
+
default_model = models.ForeignKey(
|
|
172
|
+
ChatModelOptions, on_delete=models.CASCADE, default=None, null=True, blank=True, related_name="default_model"
|
|
173
|
+
)
|
|
174
|
+
summarizer_model = models.ForeignKey(
|
|
175
|
+
ChatModelOptions, on_delete=models.CASCADE, default=None, null=True, blank=True, related_name="summarizer_model"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class LocalOrgConfig(BaseModel):
|
|
180
|
+
input_files = models.JSONField(default=list, null=True)
|
|
181
|
+
input_filter = models.JSONField(default=list, null=True)
|
|
182
|
+
index_heading_entries = models.BooleanField(default=False)
|
|
183
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class LocalMarkdownConfig(BaseModel):
|
|
187
|
+
input_files = models.JSONField(default=list, null=True)
|
|
188
|
+
input_filter = models.JSONField(default=list, null=True)
|
|
189
|
+
index_heading_entries = models.BooleanField(default=False)
|
|
190
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class LocalPdfConfig(BaseModel):
|
|
194
|
+
input_files = models.JSONField(default=list, null=True)
|
|
195
|
+
input_filter = models.JSONField(default=list, null=True)
|
|
196
|
+
index_heading_entries = models.BooleanField(default=False)
|
|
197
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class LocalPlaintextConfig(BaseModel):
|
|
201
|
+
input_files = models.JSONField(default=list, null=True)
|
|
202
|
+
input_filter = models.JSONField(default=list, null=True)
|
|
203
|
+
index_heading_entries = models.BooleanField(default=False)
|
|
204
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class SearchModelConfig(BaseModel):
|
|
208
|
+
class ModelType(models.TextChoices):
|
|
209
|
+
TEXT = "text"
|
|
210
|
+
|
|
211
|
+
# This is the model name exposed to users on their settings page
|
|
212
|
+
name = models.CharField(max_length=200, default="default")
|
|
213
|
+
# Type of content the model can generate embeddings for
|
|
214
|
+
model_type = models.CharField(max_length=200, choices=ModelType.choices, default=ModelType.TEXT)
|
|
215
|
+
# Bi-encoder model of sentence-transformer type to load from HuggingFace
|
|
216
|
+
bi_encoder = models.CharField(max_length=200, default="thenlper/gte-small")
|
|
217
|
+
# Config passed to the sentence-transformer model constructor. E.g. device="cuda:0", trust_remote_server=True etc.
|
|
218
|
+
bi_encoder_model_config = models.JSONField(default=dict, blank=True)
|
|
219
|
+
# Query encode configs like prompt, precision, normalize_embeddings, etc. for sentence-transformer models
|
|
220
|
+
bi_encoder_query_encode_config = models.JSONField(default=dict, blank=True)
|
|
221
|
+
# Docs encode configs like prompt, precision, normalize_embeddings, etc. for sentence-transformer models
|
|
222
|
+
bi_encoder_docs_encode_config = models.JSONField(default=dict, blank=True)
|
|
223
|
+
# Cross-encoder model of sentence-transformer type to load from HuggingFace
|
|
224
|
+
cross_encoder = models.CharField(max_length=200, default="mixedbread-ai/mxbai-rerank-xsmall-v1")
|
|
225
|
+
# Inference server API endpoint to use for embeddings inference. Bi-encoder model should be hosted on this server
|
|
226
|
+
embeddings_inference_endpoint = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
227
|
+
# Inference server API Key to use for embeddings inference. Bi-encoder model should be hosted on this server
|
|
228
|
+
embeddings_inference_endpoint_api_key = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
229
|
+
# Inference server API endpoint to use for embeddings inference. Cross-encoder model should be hosted on this server
|
|
230
|
+
cross_encoder_inference_endpoint = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
231
|
+
# Inference server API Key to use for embeddings inference. Cross-encoder model should be hosted on this server
|
|
232
|
+
cross_encoder_inference_endpoint_api_key = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class TextToImageModelConfig(BaseModel):
|
|
236
|
+
class ModelType(models.TextChoices):
|
|
237
|
+
OPENAI = "openai"
|
|
238
|
+
STABILITYAI = "stability-ai"
|
|
239
|
+
|
|
240
|
+
model_name = models.CharField(max_length=200, default="dall-e-3")
|
|
241
|
+
model_type = models.CharField(max_length=200, choices=ModelType.choices, default=ModelType.OPENAI)
|
|
242
|
+
api_key = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
243
|
+
openai_config = models.ForeignKey(
|
|
244
|
+
OpenAIProcessorConversationConfig, on_delete=models.CASCADE, default=None, null=True, blank=True
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
def clean(self):
|
|
248
|
+
# Custom validation logic
|
|
249
|
+
error = {}
|
|
250
|
+
if self.model_type == self.ModelType.OPENAI:
|
|
251
|
+
if self.api_key and self.openai_config:
|
|
252
|
+
error[
|
|
253
|
+
"api_key"
|
|
254
|
+
] = "Both API key and OpenAI config cannot be set for OpenAI models. Please set only one of them."
|
|
255
|
+
error[
|
|
256
|
+
"openai_config"
|
|
257
|
+
] = "Both API key and OpenAI config cannot be set for OpenAI models. Please set only one of them."
|
|
258
|
+
if self.model_type != self.ModelType.OPENAI:
|
|
259
|
+
if not self.api_key:
|
|
260
|
+
error["api_key"] = "The API key field must be set for non OpenAI models."
|
|
261
|
+
if self.openai_config:
|
|
262
|
+
error["openai_config"] = "OpenAI config cannot be set for non OpenAI models."
|
|
263
|
+
if error:
|
|
264
|
+
raise ValidationError(error)
|
|
265
|
+
|
|
266
|
+
def save(self, *args, **kwargs):
|
|
267
|
+
self.clean()
|
|
268
|
+
super().save(*args, **kwargs)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class SpeechToTextModelOptions(BaseModel):
|
|
272
|
+
class ModelType(models.TextChoices):
|
|
273
|
+
OPENAI = "openai"
|
|
274
|
+
OFFLINE = "offline"
|
|
275
|
+
|
|
276
|
+
model_name = models.CharField(max_length=200, default="base")
|
|
277
|
+
model_type = models.CharField(max_length=200, choices=ModelType.choices, default=ModelType.OFFLINE)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
class UserConversationConfig(BaseModel):
|
|
281
|
+
user = models.OneToOneField(KhojUser, on_delete=models.CASCADE)
|
|
282
|
+
setting = models.ForeignKey(ChatModelOptions, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class UserVoiceModelConfig(BaseModel):
|
|
286
|
+
user = models.OneToOneField(KhojUser, on_delete=models.CASCADE)
|
|
287
|
+
setting = models.ForeignKey(VoiceModelOption, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
class UserSearchModelConfig(BaseModel):
|
|
291
|
+
user = models.OneToOneField(KhojUser, on_delete=models.CASCADE)
|
|
292
|
+
setting = models.ForeignKey(SearchModelConfig, on_delete=models.CASCADE)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class UserTextToImageModelConfig(BaseModel):
|
|
296
|
+
user = models.OneToOneField(KhojUser, on_delete=models.CASCADE)
|
|
297
|
+
setting = models.ForeignKey(TextToImageModelConfig, on_delete=models.CASCADE)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class Conversation(BaseModel):
|
|
301
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
302
|
+
conversation_log = models.JSONField(default=dict)
|
|
303
|
+
client = models.ForeignKey(ClientApplication, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
|
304
|
+
slug = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
305
|
+
title = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
306
|
+
agent = models.ForeignKey(Agent, on_delete=models.SET_NULL, default=None, null=True, blank=True)
|
|
307
|
+
file_filters = models.JSONField(default=list)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
class PublicConversation(BaseModel):
|
|
311
|
+
source_owner = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
312
|
+
conversation_log = models.JSONField(default=dict)
|
|
313
|
+
slug = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
314
|
+
title = models.CharField(max_length=200, default=None, null=True, blank=True)
|
|
315
|
+
agent = models.ForeignKey(Agent, on_delete=models.SET_NULL, default=None, null=True, blank=True)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
@receiver(pre_save, sender=PublicConversation)
|
|
319
|
+
def verify_public_conversation(sender, instance, **kwargs):
|
|
320
|
+
def generate_random_alphanumeric(length):
|
|
321
|
+
characters = "0123456789abcdefghijklmnopqrstuvwxyz"
|
|
322
|
+
return "".join(choice(characters) for _ in range(length))
|
|
323
|
+
|
|
324
|
+
# check if this is a new instance
|
|
325
|
+
if instance._state.adding:
|
|
326
|
+
slug = re.sub(r"\W+", "-", instance.slug.lower())[:50]
|
|
327
|
+
observed_random_id = set()
|
|
328
|
+
while PublicConversation.objects.filter(slug=slug).exists():
|
|
329
|
+
try:
|
|
330
|
+
random_id = generate_random_alphanumeric(7)
|
|
331
|
+
except IndexError:
|
|
332
|
+
raise ValidationError(
|
|
333
|
+
"Unable to generate a unique slug for the Public Conversation. Please try again later."
|
|
334
|
+
)
|
|
335
|
+
observed_random_id.add(random_id)
|
|
336
|
+
slug = f"{slug}-{random_id}"
|
|
337
|
+
instance.slug = slug
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class ReflectiveQuestion(BaseModel):
|
|
341
|
+
question = models.CharField(max_length=500)
|
|
342
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class Entry(BaseModel):
|
|
346
|
+
class EntryType(models.TextChoices):
|
|
347
|
+
IMAGE = "image"
|
|
348
|
+
PDF = "pdf"
|
|
349
|
+
PLAINTEXT = "plaintext"
|
|
350
|
+
MARKDOWN = "markdown"
|
|
351
|
+
ORG = "org"
|
|
352
|
+
NOTION = "notion"
|
|
353
|
+
GITHUB = "github"
|
|
354
|
+
CONVERSATION = "conversation"
|
|
355
|
+
DOCX = "docx"
|
|
356
|
+
|
|
357
|
+
class EntrySource(models.TextChoices):
|
|
358
|
+
COMPUTER = "computer"
|
|
359
|
+
NOTION = "notion"
|
|
360
|
+
GITHUB = "github"
|
|
361
|
+
|
|
362
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
|
363
|
+
embeddings = VectorField(dimensions=None)
|
|
364
|
+
raw = models.TextField()
|
|
365
|
+
compiled = models.TextField()
|
|
366
|
+
heading = models.CharField(max_length=1000, default=None, null=True, blank=True)
|
|
367
|
+
file_source = models.CharField(max_length=30, choices=EntrySource.choices, default=EntrySource.COMPUTER)
|
|
368
|
+
file_type = models.CharField(max_length=30, choices=EntryType.choices, default=EntryType.PLAINTEXT)
|
|
369
|
+
file_path = models.CharField(max_length=400, default=None, null=True, blank=True)
|
|
370
|
+
file_name = models.CharField(max_length=400, default=None, null=True, blank=True)
|
|
371
|
+
url = models.URLField(max_length=400, default=None, null=True, blank=True)
|
|
372
|
+
hashed_value = models.CharField(max_length=100)
|
|
373
|
+
corpus_id = models.UUIDField(default=uuid.uuid4, editable=False)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
class FileObject(BaseModel):
|
|
377
|
+
# Same as Entry but raw will be a much larger string
|
|
378
|
+
file_name = models.CharField(max_length=400, default=None, null=True, blank=True)
|
|
379
|
+
raw_text = models.TextField()
|
|
380
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
class EntryDates(BaseModel):
|
|
384
|
+
date = models.DateField()
|
|
385
|
+
entry = models.ForeignKey(Entry, on_delete=models.CASCADE, related_name="embeddings_dates")
|
|
386
|
+
|
|
387
|
+
class Meta:
|
|
388
|
+
indexes = [
|
|
389
|
+
models.Index(fields=["date"]),
|
|
390
|
+
]
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class UserRequests(BaseModel):
|
|
394
|
+
user = models.ForeignKey(KhojUser, on_delete=models.CASCADE)
|
|
395
|
+
slug = models.CharField(max_length=200)
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
class DataStore(BaseModel):
|
|
399
|
+
key = models.CharField(max_length=200, unique=True)
|
|
400
|
+
value = models.JSONField(default=dict)
|
|
401
|
+
private = models.BooleanField(default=False)
|
|
402
|
+
owner = models.ForeignKey(KhojUser, on_delete=models.CASCADE, default=None, null=True, blank=True)
|
khoj/database/tests.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Khoj Feedback Form</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<body style="font-family: 'Verdana', sans-serif; font-weight: 400; font-style: normal; padding: 0; text-align: left; width: 600px; margin: 20px auto;">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
9
|
+
<a class="logo" href="https://khoj.dev" target="_blank" style="text-decoration: none; text-decoration: underline dotted;">
|
|
10
|
+
<img src="https://khoj.dev/khoj-logo-sideways-500.png" alt="Khoj Logo" style="width: 100px;">
|
|
11
|
+
</a>
|
|
12
|
+
<div class="calls-to-action" style="margin-top: 20px;">
|
|
13
|
+
<div>
|
|
14
|
+
<h1 style="color: #333; font-size: large; font-weight: bold; margin: 10px; line-height: 1.5; background-color: #fee285; padding: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.5);">User Feedback:</h1>
|
|
15
|
+
<div>
|
|
16
|
+
<h3>User Query</h3>
|
|
17
|
+
<p>{{uquery}}</p>
|
|
18
|
+
</div>
|
|
19
|
+
<div>
|
|
20
|
+
<h3>Khoj's Response</h3>
|
|
21
|
+
{{kquery}}
|
|
22
|
+
</div>
|
|
23
|
+
<div>
|
|
24
|
+
<h3>Sentiment</h3>
|
|
25
|
+
<p>{{sentiment}}</p>
|
|
26
|
+
</div>
|
|
27
|
+
<div>
|
|
28
|
+
<h3>User Email</h3>
|
|
29
|
+
<p>{{user_email}}</p>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Welcome to Khoj</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<body style="font-family: 'Verdana', sans-serif; font-weight: 400; font-style: normal; padding: 0; text-align: left; width: 600px; margin: 20px auto;">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
9
|
+
<a class="logo" href="https://khoj.dev" target="_blank" style="text-decoration: none; text-decoration: underline dotted;">
|
|
10
|
+
<img src="https://khoj.dev/khoj-logo-sideways-500.png" alt="Khoj Logo" style="width: 100px;">
|
|
11
|
+
</a>
|
|
12
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">Hi! <a href="{{ link }}" target="_blank" style="text-decoration: none; text-decoration: underline dotted;">Click here to sign in on this browser.</a></p>
|
|
13
|
+
|
|
14
|
+
<p style="color: #333; font-size: large; margin-top: 20px; padding: 0; line-height: 1.5;">- The Khoj Team</p>
|
|
15
|
+
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Khoj AI - Automation</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<body style="font-family: 'Verdana', sans-serif; font-weight: 400; font-style: normal; padding: 0; text-align: left; width: 600px; margin: 20px auto;">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
9
|
+
<a class="logo" href="https://khoj.dev" target="_blank" style="text-decoration: none; text-decoration: underline dotted;">
|
|
10
|
+
<img src="https://khoj.dev/khoj-logo-sideways-500.png" alt="Khoj Logo" style="width: 100px;">
|
|
11
|
+
</a>
|
|
12
|
+
<div class="calls-to-action" style="margin-top: 20px;">
|
|
13
|
+
<div>
|
|
14
|
+
<h1 style="color: #333; font-size: large; font-weight: bold; margin: 0; line-height: 1.5; background-color: #fee285; padding: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.5);">Your Automation, From Your Personal AI (Preview)</h1>
|
|
15
|
+
|
|
16
|
+
<div style="display: grid; grid-template-columns: 1fr; grid-gap: 12px; margin-top: 20px;">
|
|
17
|
+
<div style="border: 1px solid black; border-radius: 8px; padding: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0); margin-top: 20px;">
|
|
18
|
+
<a href="https://app.khoj.dev/automations" style="text-decoration: none; text-decoration: underline dotted;">
|
|
19
|
+
<h3 style="color: #333; font-size: large; margin: 0; padding: 0; line-height: 2.0; background-color: #b8f1c7; padding: 8px; ">{{subject}}</h3>
|
|
20
|
+
</a>
|
|
21
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">{{result}}</p>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">The automation I ran on your behalf: {{query}}</p>
|
|
25
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">You can manage your automations via <a href="https://app.khoj.dev/automations">the settings page</a>.</p>
|
|
26
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">This is an experimental feature. Please share any feedback with <a href="mailto:team@khoj.dev">team@khoj.dev</a>.</p>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
<p style="color: #333; font-size: large; margin-top: 20px; padding: 0; line-height: 1.5;">- Khoj</p>
|
|
30
|
+
<table style="width: 100%; margin-top: 20px;">
|
|
31
|
+
<tr>
|
|
32
|
+
<td style="text-align: center;"><a href="https://docs.khoj.dev" target="_blank" style="padding: 8px; color: #333; background-color: #fee285; border-radius: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0);">Docs</a></td>
|
|
33
|
+
<td style="text-align: center;"><a href="https://github.com/khoj-ai/khoj" target="_blank" style="padding: 8px; color: #333; background-color: #fee285; border-radius: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0);">GitHub</a></td>
|
|
34
|
+
<td style="text-align: center;"><a href="https://twitter.com/khoj_ai" target="_blank" style="padding: 8px; color: #333; background-color: #fee285; border-radius: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0);">Twitter</a></td>
|
|
35
|
+
<td style="text-align: center;"><a href="https://www.linkedin.com/company/khoj-ai" target="_blank" style="padding: 8px; color: #333; background-color: #fee285; border-radius: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0);">LinkedIn</a></td>
|
|
36
|
+
</tr>
|
|
37
|
+
</table>
|
|
38
|
+
|
|
39
|
+
</body>
|
|
40
|
+
</html>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Welcome to Khoj</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<body style="font-family: 'Verdana', sans-serif; font-weight: 400; font-style: normal; padding: 0; text-align: left; width: 600px; margin: 20px auto;">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
9
|
+
<a class="logo" href="https://khoj.dev" target="_blank" style="text-decoration: none; text-decoration: underline dotted;">
|
|
10
|
+
<img src="https://khoj.dev/khoj-logo-sideways-500.png" alt="Khoj Logo" style="width: 100px;">
|
|
11
|
+
</a>
|
|
12
|
+
<div class="calls-to-action" style="margin-top: 20px;">
|
|
13
|
+
<div>
|
|
14
|
+
<h1 style="color: #333; font-size: large; font-weight: bold; margin: 0; line-height: 1.5; background-color: #fee285; padding: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.5);">Merge AI with your brain</h1>
|
|
15
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">Hi {{name}}! We are psyched to be part of your journey with personal AI. To better help you, we're committed to staying transparent, accessible, and completely open-source.</p>
|
|
16
|
+
<a class="button" href="https://app.khoj.dev" target="_blank" style="display: block; width: 200px; text-align: center; padding: 10px; margin-top: 20px; color: #333; background-color: #fee285; text-decoration: none; border-radius: 5px; font-weight: bold; transition: background-color 0.3s ease; box-shadow: 6px 6px rgba(0, 0, 0, 1.0); padding: 4px; font-size: large; text-transform: uppercase;">Get Started</a>
|
|
17
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">You're about to get a whole lot more productive.</p>
|
|
18
|
+
|
|
19
|
+
<div style="display: grid; grid-template-columns: 1fr 1fr; grid-gap: 12px; margin-top: 20px;">
|
|
20
|
+
<div style="border: 1px solid black; border-radius: 8px; padding: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0); margin-top: 20px;">
|
|
21
|
+
<a href="https://docs.khoj.dev/features/online_search" style="text-decoration: none; text-decoration: underline dotted;">
|
|
22
|
+
<h3 style="color: #333; font-size: large; margin: 0; padding: 0; line-height: 2.0; background-color: #b8f1c7; padding: 8px; ">Ditch the search bar</h3>
|
|
23
|
+
</a>
|
|
24
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">You don't need to click around Google results and sift through information yourself, because Khoj is connected to the internet.</p>
|
|
25
|
+
</div>
|
|
26
|
+
<div style="border: 1px solid black; border-radius: 8px; padding: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0); margin-top: 20px;">
|
|
27
|
+
<a href="https://app.khoj.dev/agents" style="text-decoration: none; text-decoration: underline dotted;">
|
|
28
|
+
<h3 style="color: #333; font-size: large; margin: 0; padding: 0; line-height: 2.0; background-color: #b8f1c7; padding: 8px;">Get a village, not just an agent</h3>
|
|
29
|
+
</a>
|
|
30
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">Khoj can fill the need for more specialized assistance, <a href="https://blog.khoj.dev/posts/using-khoj-for-studying/">such as tutoring</a>, with its curated agents. You get a whole team, always available.</p>
|
|
31
|
+
</div>
|
|
32
|
+
<div style="border: 1px solid black; border-radius: 8px; padding: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0); margin-top: 20px;">
|
|
33
|
+
<a href="https://docs.khoj.dev/category/clients" style="text-decoration: none; text-decoration: underline dotted;">
|
|
34
|
+
<h3 style="color: #333; font-size: large; margin: 0; padding: 0; line-height: 2.0; background-color: #b8f1c7; padding: 8px;">Available where you are</h3>
|
|
35
|
+
</a>
|
|
36
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">Build on top of your digital brain. Khoj stores whatever data you share with it, so you can get answers from your personal notes and documents in your native language. You can engage from your desktop, Obsidian, WhatsApp, or the web.</p>
|
|
37
|
+
</div>
|
|
38
|
+
<div style="border: 1px solid black; border-radius: 8px; padding: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0); margin-top: 20px;">
|
|
39
|
+
<a href="https://blog.khoj.dev/posts/how-khoj-generates-images/" style="text-decoration: none; text-decoration: underline dotted;">
|
|
40
|
+
<h3 style="color: #333; font-size: large; margin: 0; padding: 0; line-height: 2.0; background-color: #b8f1c7; padding: 8px;">Create rich, contextual images</h3>
|
|
41
|
+
</a>
|
|
42
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">With your shared data, Khoj can help you create astoundingly personal images depicting scenes of what's important to you.</p>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
<p style="color: #333; font-size: medium; margin-top: 20px; padding: 0; line-height: 1.5;">Like something? Dislike something? Searching for some other magical feature? Our inbox is always open for feedback! Contact us on team@khoj.dev at anytime.</p>
|
|
48
|
+
|
|
49
|
+
<p style="color: #333; font-size: large; margin-top: 20px; padding: 0; line-height: 1.5;">- The Khoj Team</p>
|
|
50
|
+
<table style="width: 100%; margin-top: 20px;">
|
|
51
|
+
<tr>
|
|
52
|
+
<td style="text-align: center;"><a href="https://docs.khoj.dev" target="_blank" style="padding: 8px; color: #333; background-color: #fee285; border-radius: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0);">Docs</a></td>
|
|
53
|
+
<td style="text-align: center;"><a href="https://github.com/khoj-ai/khoj" target="_blank" style="padding: 8px; color: #333; background-color: #fee285; border-radius: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0);">GitHub</a></td>
|
|
54
|
+
<td style="text-align: center;"><a href="https://twitter.com/khoj_ai" target="_blank" style="padding: 8px; color: #333; background-color: #fee285; border-radius: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0);">Twitter</a></td>
|
|
55
|
+
<td style="text-align: center;"><a href="https://www.linkedin.com/company/khoj-ai" target="_blank" style="padding: 8px; color: #333; background-color: #fee285; border-radius: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0);">LinkedIn</a></td>
|
|
56
|
+
<td style="text-align: center;"><a href="https://discord.gg/BDgyabRM6e" target="_blank" style="padding: 8px; color: #333; background-color: #fee285; border-radius: 8px; box-shadow: 6px 6px rgba(0, 0, 0, 1.0);">Discord</a></td>
|
|
57
|
+
</tr>
|
|
58
|
+
</table>
|
|
59
|
+
|
|
60
|
+
</body>
|
|
61
|
+
</html>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Khoj: An AI Personal Assistant for your digital brain</title>
|
|
5
|
+
<link rel="icon" type="image/png" sizes="128x128" href="/static/assets/icons/favicon-128x128.png?v={{ khoj_version }}">
|
|
6
|
+
<link rel="manifest" href="/static/khoj.webmanifest?v={{ khoj_version }}">
|
|
7
|
+
<link rel="stylesheet" href="/static/assets/khoj.css?v={{ khoj_version }}">
|
|
8
|
+
</head>
|
|
9
|
+
<body class="not-found">
|
|
10
|
+
<!--Add Header Logo and Nav Pane-->
|
|
11
|
+
{% import 'utils.html' as utils %}
|
|
12
|
+
{{ utils.heading_pane(user_photo, username, is_active, has_documents) }}
|
|
13
|
+
|
|
14
|
+
<header class=”header”>
|
|
15
|
+
<h1>Oops, this is awkward. Looks like there's nothing here.</h1>
|
|
16
|
+
</header>
|
|
17
|
+
<a class="redirect-link" href="/">Go Home</a>
|
|
18
|
+
|
|
19
|
+
<footer class=”footer”>
|
|
20
|
+
</footer>
|
|
21
|
+
</body>
|
|
22
|
+
<style>
|
|
23
|
+
body.not-found {
|
|
24
|
+
padding: 0 10%
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
body {
|
|
28
|
+
background-color: var(--background-color);
|
|
29
|
+
color: var(--main-text-color);
|
|
30
|
+
text-align: center;
|
|
31
|
+
font-family: var(--font-family);
|
|
32
|
+
font-size: medium;
|
|
33
|
+
font-weight: 300;
|
|
34
|
+
line-height: 1.5em;
|
|
35
|
+
height: 100vh;
|
|
36
|
+
margin: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
body a.redirect-link {
|
|
40
|
+
font-size: 18px;
|
|
41
|
+
font-weight: bold;
|
|
42
|
+
background-color: var(--primary);
|
|
43
|
+
text-decoration: none;
|
|
44
|
+
border: 1px solid var(--main-text-color);
|
|
45
|
+
color: var(--main-text-color);
|
|
46
|
+
border-radius: 8px;
|
|
47
|
+
padding: 4px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
body a.redirect-link:hover {
|
|
51
|
+
background-color: var(--main-text-color);
|
|
52
|
+
color: var(--primary);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
</style>
|
|
56
|
+
</html>
|