khoj 1.23.3.dev4__py3-none-any.whl → 1.23.4.dev4__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/database/adapters/__init__.py +8 -12
- khoj/database/migrations/0063_conversation_temp_id.py +36 -0
- khoj/database/migrations/0064_remove_conversation_temp_id_alter_conversation_id.py +86 -0
- khoj/database/models/__init__.py +1 -1
- khoj/interface/compiled/404/index.html +1 -1
- khoj/interface/compiled/_next/static/chunks/1603-d643510c2c0b8871.js +1 -0
- khoj/interface/compiled/_next/static/chunks/2697-5b013077cfa7aaf0.js +1 -0
- khoj/interface/compiled/_next/static/chunks/{1906-1747a36c336df02c.js → 4051-3dc2df557ccb5213.js} +2 -2
- khoj/interface/compiled/_next/static/chunks/8423-62ac6c832be2461b.js +1 -0
- khoj/interface/compiled/_next/static/chunks/9178-d8cec50b2cec38da.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/agents/page-830581af9f40707b.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/automations/{page-6ea3381528603372.js → page-cc875a656df43713.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/chat/page-4b76ccfca1a6154c.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/factchecker/{page-04a19ab1a988976f.js → page-bb320ff7d4dee716.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/page-60193524cf570002.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/search/page-4bceb5b0df9cfd66.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/settings/page-532ed8b778a0b40d.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/share/chat/page-3ddcb1cef09264fb.js +1 -0
- khoj/interface/compiled/_next/static/chunks/{webpack-072d1cbdec7e1782.js → webpack-de28762883e5816d.js} +1 -1
- khoj/interface/compiled/_next/static/css/{a3530ec58b0b660f.css → 3e1f1fdd70775091.css} +1 -1
- khoj/interface/compiled/_next/static/css/4cae6c0e5c72fb2d.css +1 -0
- khoj/interface/compiled/_next/static/css/507bf83cc17d2b53.css +1 -0
- khoj/interface/compiled/_next/static/css/6bde1f2045622ef7.css +1 -0
- khoj/interface/compiled/_next/static/css/93c1302668e4a828.css +25 -0
- khoj/interface/compiled/_next/static/css/e41ec62af8ee4e38.css +1 -0
- khoj/interface/compiled/agents/index.html +1 -1
- khoj/interface/compiled/agents/index.txt +2 -2
- khoj/interface/compiled/automations/index.html +1 -1
- khoj/interface/compiled/automations/index.txt +2 -2
- khoj/interface/compiled/chat/index.html +1 -1
- khoj/interface/compiled/chat/index.txt +2 -2
- khoj/interface/compiled/factchecker/index.html +1 -1
- khoj/interface/compiled/factchecker/index.txt +2 -2
- khoj/interface/compiled/index.html +1 -1
- khoj/interface/compiled/index.txt +2 -2
- khoj/interface/compiled/search/index.html +1 -1
- khoj/interface/compiled/search/index.txt +2 -2
- khoj/interface/compiled/settings/index.html +1 -1
- khoj/interface/compiled/settings/index.txt +2 -2
- khoj/interface/compiled/share/chat/index.html +1 -1
- khoj/interface/compiled/share/chat/index.txt +2 -2
- khoj/interface/email/task.html +31 -34
- khoj/interface/email/welcome.html +82 -53
- khoj/main.py +1 -1
- khoj/processor/content/images/image_to_entries.py +6 -4
- khoj/processor/conversation/utils.py +13 -8
- khoj/routers/api.py +1 -1
- khoj/routers/api_chat.py +14 -45
- khoj/routers/helpers.py +12 -7
- khoj/utils/cli.py +6 -0
- khoj/utils/constants.py +9 -2
- khoj/utils/initialization.py +158 -71
- {khoj-1.23.3.dev4.dist-info → khoj-1.23.4.dev4.dist-info}/METADATA +2 -2
- {khoj-1.23.3.dev4.dist-info → khoj-1.23.4.dev4.dist-info}/RECORD +60 -60
- khoj/database/migrations/0063_conversation_add_unique_id_field.py +0 -19
- khoj/database/migrations/0064_populate_unique_id.py +0 -20
- khoj/database/migrations/0065_add_unique_constraint_to_unique_id.py +0 -17
- khoj/interface/compiled/_next/static/chunks/1603-7914d7712a47690d.js +0 -1
- khoj/interface/compiled/_next/static/chunks/8423-14fc72aec9104ce9.js +0 -1
- khoj/interface/compiled/_next/static/chunks/9178-c153fc402c970365.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/agents/page-cd8e2ba85287e1f6.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/chat/page-5752b57c1e43e8a7.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/page-cd8d5d12595676d7.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/search/page-fa15807b1ad7e30b.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/settings/page-1a2acc46cdabaf4a.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/share/chat/page-e20f54450d3ce6c0.js +0 -1
- khoj/interface/compiled/_next/static/css/2272c73fc7a3b571.css +0 -1
- khoj/interface/compiled/_next/static/css/3e49e5ee49c6bda1.css +0 -25
- khoj/interface/compiled/_next/static/css/43939edc2f9b2043.css +0 -1
- khoj/interface/compiled/_next/static/css/553f9cdcc7a2bcd6.css +0 -1
- khoj/interface/compiled/_next/static/css/592ca99f5122e75a.css +0 -1
- /khoj/interface/compiled/_next/static/{d3ySlDLLYAYu1Jr-Dc35R → OnQKAWQ2iyKK5wApHgZtb}/_buildManifest.js +0 -0
- /khoj/interface/compiled/_next/static/{d3ySlDLLYAYu1Jr-Dc35R → OnQKAWQ2iyKK5wApHgZtb}/_ssgManifest.js +0 -0
- /khoj/interface/compiled/_next/static/chunks/{7023-52c1be60135eb057.js → 7023-1074a582ec989284.js} +0 -0
- {khoj-1.23.3.dev4.dist-info → khoj-1.23.4.dev4.dist-info}/WHEEL +0 -0
- {khoj-1.23.3.dev4.dist-info → khoj-1.23.4.dev4.dist-info}/entry_points.txt +0 -0
- {khoj-1.23.3.dev4.dist-info → khoj-1.23.4.dev4.dist-info}/licenses/LICENSE +0 -0
@@ -1,61 +1,90 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
<
|
7
|
-
<
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
<div
|
13
|
-
|
14
|
-
<
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
<
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
2
|
+
<html lang="en">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
+
<title>Welcome to Khoj</title>
|
8
|
+
</head>
|
9
|
+
|
10
|
+
<body
|
11
|
+
style="font-family: 'Arial', sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f5f5f5;">
|
12
|
+
<div
|
13
|
+
style="background-color: #ffffff; border-radius: 10px; box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); padding: 30px;">
|
14
|
+
<a href="https://khoj.dev" target="_blank"
|
15
|
+
style="display: block; text-align: center; margin-bottom: 20px; text-decoration: none;">
|
16
|
+
<img src="https://assets.khoj.dev/khoj_logo.png" alt="Khoj Logo" style="width: 120px;">
|
17
|
+
</a>
|
18
|
+
|
19
|
+
<h1
|
20
|
+
style="font-size: 24px; color: #2c3e50; margin-bottom: 20px; text-align: center; border-bottom: 2px solid #FFA07A; padding-bottom: 10px;">
|
21
|
+
Merge AI with your brain</h1>
|
22
|
+
|
23
|
+
<p style="font-size: 16px; color: #333; margin-bottom: 20px;">Hi {{name}}! We are psyched to be part of your
|
24
|
+
journey with personal AI. To better help you, we're committed to staying transparent, accessible, and
|
25
|
+
completely open-source.</p>
|
26
|
+
|
27
|
+
<a href="https://app.khoj.dev" target="_blank"
|
28
|
+
style="display: block; width: 200px; text-align: center; padding: 10px; margin: 20px auto; background-color: #FFA07A; color: #ffffff; text-decoration: none; border-radius: 5px; font-weight: bold; font-size: 16px; text-transform: uppercase;">Get
|
29
|
+
Started</a>
|
30
|
+
|
31
|
+
<p style="font-size: 16px; color: #333; margin-bottom: 20px;">You're about to get a whole lot more productive.
|
32
|
+
</p>
|
33
|
+
<a href="https://docs.khoj.dev/features/online_search"
|
34
|
+
style="color: #FFA07A; text-decoration: none; font-weight: bold; font-size: 14px;">
|
35
|
+
<div style="display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px; margin-bottom: 20px;">
|
36
|
+
<div style="background-color: #f8f9fa; border-left: 4px solid #FFA07A; padding: 15px;">
|
37
|
+
<h3 style="color: #2c3e50; margin-top: 0; font-size: 18px;">Ditch the search bar</h3>
|
38
|
+
<p style="font-size: 14px; color: #666; margin-bottom: 0;">You don't need to click around Google
|
39
|
+
results
|
40
|
+
and sift through information yourself, because Khoj is connected to the internet.</p>
|
41
|
+
</div>
|
42
|
+
</a>
|
43
|
+
<a href="https://app.khoj.dev/agents"
|
44
|
+
style="color: #FFA07A; text-decoration: none; font-weight: bold; font-size: 14px;">
|
45
|
+
<div style="background-color: #f8f9fa; border-left: 4px solid #FFA07A; padding: 15px;">
|
46
|
+
<h3 style="color: #2c3e50; margin-top: 0; font-size: 18px;">Get a village, not just an agent</h3>
|
47
|
+
<p style="font-size: 14px; color: #666; margin-bottom: 0;">Khoj can fill the need for more specialized
|
48
|
+
assistance, such as tutoring, with its curated agents. You get a whole team, always available.</p>
|
31
49
|
</div>
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
<
|
50
|
+
</a>
|
51
|
+
<a href="https://docs.khoj.dev/category/clients"
|
52
|
+
style="color: #FFA07A; text-decoration: none; font-weight: bold; font-size: 14px;">
|
53
|
+
<div style="background-color: #f8f9fa; border-left: 4px solid #FFA07A; padding: 15px;">
|
54
|
+
<h3 style="color: #2c3e50; margin-top: 0; font-size: 18px;">Activate your data</h3>
|
55
|
+
<p style="font-size: 14px; color: #666; margin-bottom: 0;">Build on top of your digital brain. Khoj
|
56
|
+
stores whatever data you share with it, so you can get answers from your personal notes and
|
57
|
+
documents in your native language.</p>
|
37
58
|
</div>
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
<
|
59
|
+
</a>
|
60
|
+
<a href="https://blog.khoj.dev/posts/how-khoj-generates-images/"
|
61
|
+
style="color: #FFA07A; text-decoration: none; font-weight: bold; font-size: 14px;">
|
62
|
+
<div style="background-color: #f8f9fa; border-left: 4px solid #FFA07A; padding: 15px;">
|
63
|
+
<h3 style="color: #2c3e50; margin-top: 0; font-size: 18px;">Create rich, contextual images</h3>
|
64
|
+
<p style="font-size: 14px; color: #666; margin-bottom: 0;">With your shared data, Khoj can help you
|
65
|
+
create astoundingly personal images depicting scenes of what's important to you.</p>
|
43
66
|
</div>
|
44
|
-
</
|
67
|
+
</a>
|
45
68
|
</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! Reply to this email and say hi to introduce yourself 👋🏽.</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
69
|
|
70
|
+
<p style="font-size: 16px; color: #333; margin-bottom: 20px;">Like something? Dislike something? Searching for
|
71
|
+
some other magical feature? Our inbox is always open for feedback! Reply to this email and say hi to
|
72
|
+
introduce yourself 👋🏽.</p>
|
73
|
+
<div style="font-size: 18px; font-weight: bold; margin-top: 30px; text-align: right;">- The Khoj Team</div>
|
74
|
+
|
75
|
+
<div style="margin-top: 30px; text-align: center;">
|
76
|
+
<a href="https://docs.khoj.dev" target="_blank"
|
77
|
+
style="display: inline-block; margin: 0 10px; padding: 8px 15px; background-color: #FFA07A; color: #ffffff; text-decoration: none; border-radius: 5px;">Docs</a>
|
78
|
+
<a href="https://github.com/khoj-ai/khoj" target="_blank"
|
79
|
+
style="display: inline-block; margin: 0 10px; padding: 8px 15px; background-color: #FFA07A; color: #ffffff; text-decoration: none; border-radius: 5px;">GitHub</a>
|
80
|
+
<a href="https://twitter.com/khoj_ai" target="_blank"
|
81
|
+
style="display: inline-block; margin: 0 10px; padding: 8px 15px; background-color: #FFA07A; color: #ffffff; text-decoration: none; border-radius: 5px;">Twitter</a>
|
82
|
+
<a href="https://www.linkedin.com/company/khoj-ai" target="_blank"
|
83
|
+
style="display: inline-block; margin: 0 10px; padding: 8px 15px; background-color: #FFA07A; color: #ffffff; text-decoration: none; border-radius: 5px;">LinkedIn</a>
|
84
|
+
<a href="https://discord.gg/BDgyabRM6e" target="_blank"
|
85
|
+
style="display: inline-block; margin: 0 10px; padding: 8px 15px; background-color: #FFA07A; color: #ffffff; text-decoration: none; border-radius: 5px;">Discord</a>
|
86
|
+
</div>
|
87
|
+
</div>
|
60
88
|
</body>
|
89
|
+
|
61
90
|
</html>
|
khoj/main.py
CHANGED
@@ -131,7 +131,7 @@ def run(should_start_server=True):
|
|
131
131
|
logger.info(f"📦 Initializing DB:\n{db_migrate_output.getvalue().strip()}")
|
132
132
|
logger.debug(f"🌍 Initializing Web Client:\n{collectstatic_output.getvalue().strip()}")
|
133
133
|
|
134
|
-
initialization()
|
134
|
+
initialization(not args.non_interactive)
|
135
135
|
|
136
136
|
# Create app directory, if it doesn't exist
|
137
137
|
state.config_file.parent.mkdir(parents=True, exist_ok=True)
|
@@ -4,8 +4,6 @@ import os
|
|
4
4
|
from datetime import datetime
|
5
5
|
from typing import Dict, List, Tuple
|
6
6
|
|
7
|
-
from rapidocr_onnxruntime import RapidOCR
|
8
|
-
|
9
7
|
from khoj.database.models import Entry as DbEntry
|
10
8
|
from khoj.database.models import KhojUser
|
11
9
|
from khoj.processor.content.text_to_entries import TextToEntries
|
@@ -58,7 +56,6 @@ class ImageToEntries(TextToEntries):
|
|
58
56
|
entry_to_location_map: List[Tuple[str, str]] = []
|
59
57
|
for image_file in image_files:
|
60
58
|
try:
|
61
|
-
loader = RapidOCR()
|
62
59
|
bytes = image_files[image_file]
|
63
60
|
# write the image to a temporary file
|
64
61
|
timestamp_now = datetime.utcnow().timestamp()
|
@@ -71,13 +68,18 @@ class ImageToEntries(TextToEntries):
|
|
71
68
|
bytes = image_files[image_file]
|
72
69
|
f.write(bytes)
|
73
70
|
try:
|
71
|
+
from rapidocr_onnxruntime import RapidOCR
|
72
|
+
|
73
|
+
loader = RapidOCR()
|
74
74
|
image_entries_per_file = ""
|
75
75
|
result, _ = loader(tmp_file)
|
76
76
|
if result:
|
77
77
|
expanded_entries = [text[1] for text in result]
|
78
78
|
image_entries_per_file = " ".join(expanded_entries)
|
79
79
|
except ImportError:
|
80
|
-
logger.warning(
|
80
|
+
logger.warning(
|
81
|
+
f"Unable to process image or scanned file for text: {image_file}. This file will not be indexed."
|
82
|
+
)
|
81
83
|
continue
|
82
84
|
entry_to_location_map.append((image_entries_per_file, image_file))
|
83
85
|
entries.extend([image_entries_per_file])
|
@@ -18,13 +18,20 @@ from khoj.utils.helpers import is_none_or_empty, merge_dicts
|
|
18
18
|
|
19
19
|
logger = logging.getLogger(__name__)
|
20
20
|
model_to_prompt_size = {
|
21
|
+
# OpenAI Models
|
21
22
|
"gpt-3.5-turbo": 12000,
|
22
|
-
"gpt-3.5-turbo-0125": 12000,
|
23
|
-
"gpt-4-0125-preview": 20000,
|
24
23
|
"gpt-4-turbo-preview": 20000,
|
24
|
+
"gpt-4o": 20000,
|
25
25
|
"gpt-4o-mini": 20000,
|
26
26
|
"o1-preview": 20000,
|
27
27
|
"o1-mini": 20000,
|
28
|
+
# Google Models
|
29
|
+
"gemini-1.5-flash": 20000,
|
30
|
+
"gemini-1.5-pro": 20000,
|
31
|
+
# Anthropic Models
|
32
|
+
"claude-3-5-sonnet-20240620": 20000,
|
33
|
+
"claude-3-opus-20240229": 20000,
|
34
|
+
# Offline Models
|
28
35
|
"TheBloke/Mistral-7B-Instruct-v0.2-GGUF": 3500,
|
29
36
|
"NousResearch/Hermes-2-Pro-Mistral-7B-GGUF": 3500,
|
30
37
|
"bartowski/Meta-Llama-3.1-8B-Instruct-GGUF": 20000,
|
@@ -100,7 +107,7 @@ def save_to_conversation_log(
|
|
100
107
|
inferred_queries: List[str] = [],
|
101
108
|
intent_type: str = "remember",
|
102
109
|
client_application: ClientApplication = None,
|
103
|
-
conversation_id:
|
110
|
+
conversation_id: str = None,
|
104
111
|
automation_id: str = None,
|
105
112
|
uploaded_image_url: str = None,
|
106
113
|
):
|
@@ -163,7 +170,7 @@ def generate_chatml_messages_with_context(
|
|
163
170
|
if loaded_model:
|
164
171
|
max_prompt_size = infer_max_tokens(loaded_model.n_ctx(), model_to_prompt_size.get(model_name, math.inf))
|
165
172
|
else:
|
166
|
-
max_prompt_size = model_to_prompt_size.get(model_name,
|
173
|
+
max_prompt_size = model_to_prompt_size.get(model_name, 10000)
|
167
174
|
|
168
175
|
# Scale lookback turns proportional to max prompt size supported by model
|
169
176
|
lookback_turns = max_prompt_size // 750
|
@@ -291,8 +298,6 @@ def reciprocal_conversation_to_chatml(message_pair):
|
|
291
298
|
return [ChatMessage(content=message, role=role) for message, role in zip(message_pair, ["user", "assistant"])]
|
292
299
|
|
293
300
|
|
294
|
-
def remove_json_codeblock(response):
|
301
|
+
def remove_json_codeblock(response: str):
|
295
302
|
"""Remove any markdown json codeblock formatting if present. Useful for non schema enforceable models"""
|
296
|
-
|
297
|
-
response = response[7:-3]
|
298
|
-
return response
|
303
|
+
return response.removeprefix("```json").removesuffix("```")
|
khoj/routers/api.py
CHANGED
@@ -328,7 +328,7 @@ async def extract_references_and_questions(
|
|
328
328
|
q: str,
|
329
329
|
n: int,
|
330
330
|
d: float,
|
331
|
-
conversation_id:
|
331
|
+
conversation_id: str,
|
332
332
|
conversation_commands: List[ConversationCommand] = [ConversationCommand.Default],
|
333
333
|
location_data: LocationData = None,
|
334
334
|
send_status_func: Optional[Callable] = None,
|
khoj/routers/api_chat.py
CHANGED
@@ -77,9 +77,7 @@ from khoj.routers.email import send_query_feedback
|
|
77
77
|
@api_chat.get("/conversation/file-filters/{conversation_id}", response_class=Response)
|
78
78
|
@requires(["authenticated"])
|
79
79
|
def get_file_filter(request: Request, conversation_id: str) -> Response:
|
80
|
-
conversation = ConversationAdapters.get_conversation_by_user(
|
81
|
-
request.user.object, conversation_id=int(conversation_id)
|
82
|
-
)
|
80
|
+
conversation = ConversationAdapters.get_conversation_by_user(request.user.object, conversation_id=conversation_id)
|
83
81
|
if not conversation:
|
84
82
|
return Response(content=json.dumps({"status": "error", "message": "Conversation not found"}), status_code=404)
|
85
83
|
|
@@ -95,7 +93,7 @@ def get_file_filter(request: Request, conversation_id: str) -> Response:
|
|
95
93
|
@api_chat.delete("/conversation/file-filters/bulk", response_class=Response)
|
96
94
|
@requires(["authenticated"])
|
97
95
|
def remove_files_filter(request: Request, filter: FilesFilterRequest) -> Response:
|
98
|
-
conversation_id =
|
96
|
+
conversation_id = filter.conversation_id
|
99
97
|
files_filter = filter.filenames
|
100
98
|
file_filters = ConversationAdapters.remove_files_from_filter(request.user.object, conversation_id, files_filter)
|
101
99
|
return Response(content=json.dumps(file_filters), media_type="application/json", status_code=200)
|
@@ -105,7 +103,7 @@ def remove_files_filter(request: Request, filter: FilesFilterRequest) -> Respons
|
|
105
103
|
@requires(["authenticated"])
|
106
104
|
def add_files_filter(request: Request, filter: FilesFilterRequest):
|
107
105
|
try:
|
108
|
-
conversation_id =
|
106
|
+
conversation_id = filter.conversation_id
|
109
107
|
files_filter = filter.filenames
|
110
108
|
file_filters = ConversationAdapters.add_files_to_filter(request.user.object, conversation_id, files_filter)
|
111
109
|
return Response(content=json.dumps(file_filters), media_type="application/json", status_code=200)
|
@@ -118,7 +116,7 @@ def add_files_filter(request: Request, filter: FilesFilterRequest):
|
|
118
116
|
@requires(["authenticated"])
|
119
117
|
def add_file_filter(request: Request, filter: FileFilterRequest):
|
120
118
|
try:
|
121
|
-
conversation_id =
|
119
|
+
conversation_id = filter.conversation_id
|
122
120
|
files_filter = [filter.filename]
|
123
121
|
file_filters = ConversationAdapters.add_files_to_filter(request.user.object, conversation_id, files_filter)
|
124
122
|
return Response(content=json.dumps(file_filters), media_type="application/json", status_code=200)
|
@@ -130,7 +128,7 @@ def add_file_filter(request: Request, filter: FileFilterRequest):
|
|
130
128
|
@api_chat.delete("/conversation/file-filters", response_class=Response)
|
131
129
|
@requires(["authenticated"])
|
132
130
|
def remove_file_filter(request: Request, filter: FileFilterRequest) -> Response:
|
133
|
-
conversation_id =
|
131
|
+
conversation_id = filter.conversation_id
|
134
132
|
files_filter = [filter.filename]
|
135
133
|
file_filters = ConversationAdapters.remove_files_from_filter(request.user.object, conversation_id, files_filter)
|
136
134
|
return Response(content=json.dumps(file_filters), media_type="application/json", status_code=200)
|
@@ -189,7 +187,7 @@ async def chat_starters(
|
|
189
187
|
def chat_history(
|
190
188
|
request: Request,
|
191
189
|
common: CommonQueryParams,
|
192
|
-
conversation_id: Optional[
|
190
|
+
conversation_id: Optional[str] = None,
|
193
191
|
n: Optional[int] = None,
|
194
192
|
):
|
195
193
|
user = request.user.object
|
@@ -224,7 +222,6 @@ def chat_history(
|
|
224
222
|
"conversation_id": conversation.id,
|
225
223
|
"slug": conversation.title if conversation.title else conversation.slug,
|
226
224
|
"agent": agent_metadata,
|
227
|
-
"unique_id": conversation.unique_id,
|
228
225
|
}
|
229
226
|
)
|
230
227
|
|
@@ -246,33 +243,6 @@ def chat_history(
|
|
246
243
|
return {"status": "ok", "response": meta_log}
|
247
244
|
|
248
245
|
|
249
|
-
@api_chat.get("/metadata")
|
250
|
-
def get_chat_metadata(
|
251
|
-
request: Request,
|
252
|
-
common: CommonQueryParams,
|
253
|
-
conversation_unique_id: str,
|
254
|
-
):
|
255
|
-
user = request.user.object
|
256
|
-
|
257
|
-
# Load Conversation Metadata
|
258
|
-
conversation = ConversationAdapters.get_conversation_by_unique_id(user, conversation_unique_id)
|
259
|
-
|
260
|
-
if conversation is None:
|
261
|
-
return Response(
|
262
|
-
content=json.dumps({"status": "error", "message": f"Conversation: {conversation_unique_id} not found"}),
|
263
|
-
status_code=404,
|
264
|
-
)
|
265
|
-
|
266
|
-
update_telemetry_state(
|
267
|
-
request=request,
|
268
|
-
telemetry_type="api",
|
269
|
-
api="chat_metadata",
|
270
|
-
**common.__dict__,
|
271
|
-
)
|
272
|
-
|
273
|
-
return {"status": "ok", "conversationId": conversation.id}
|
274
|
-
|
275
|
-
|
276
246
|
@api_chat.get("/share/history")
|
277
247
|
def get_shared_chat(
|
278
248
|
request: Request,
|
@@ -340,7 +310,7 @@ def get_shared_chat(
|
|
340
310
|
async def clear_chat_history(
|
341
311
|
request: Request,
|
342
312
|
common: CommonQueryParams,
|
343
|
-
conversation_id: Optional[
|
313
|
+
conversation_id: Optional[str] = None,
|
344
314
|
):
|
345
315
|
user = request.user.object
|
346
316
|
|
@@ -403,7 +373,7 @@ def fork_public_conversation(
|
|
403
373
|
def duplicate_chat_history_public_conversation(
|
404
374
|
request: Request,
|
405
375
|
common: CommonQueryParams,
|
406
|
-
conversation_id:
|
376
|
+
conversation_id: str,
|
407
377
|
):
|
408
378
|
user = request.user.object
|
409
379
|
domain = request.headers.get("host")
|
@@ -446,18 +416,17 @@ def chat_sessions(
|
|
446
416
|
conversations = conversations[:8]
|
447
417
|
|
448
418
|
sessions = conversations.values_list(
|
449
|
-
"id", "slug", "title", "agent__slug", "agent__name", "agent__avatar", "created_at", "updated_at"
|
419
|
+
"id", "slug", "title", "agent__slug", "agent__name", "agent__avatar", "created_at", "updated_at"
|
450
420
|
)
|
451
421
|
|
452
422
|
session_values = [
|
453
423
|
{
|
454
|
-
"conversation_id": session[0],
|
424
|
+
"conversation_id": str(session[0]),
|
455
425
|
"slug": session[2] or session[1],
|
456
426
|
"agent_name": session[4],
|
457
427
|
"agent_avatar": session[5],
|
458
428
|
"created": session[6].strftime("%Y-%m-%d %H:%M:%S"),
|
459
429
|
"updated": session[7].strftime("%Y-%m-%d %H:%M:%S"),
|
460
|
-
"unique_id": str(session[8]),
|
461
430
|
}
|
462
431
|
for session in sessions
|
463
432
|
]
|
@@ -484,7 +453,7 @@ async def create_chat_session(
|
|
484
453
|
# Create new Conversation Session
|
485
454
|
conversation = await ConversationAdapters.acreate_conversation_session(user, request.user.client_app, agent_slug)
|
486
455
|
|
487
|
-
response = {"conversation_id":
|
456
|
+
response = {"conversation_id": str(conversation.id)}
|
488
457
|
|
489
458
|
conversation_metadata = {
|
490
459
|
"agent": agent_slug,
|
@@ -526,7 +495,7 @@ async def set_conversation_title(
|
|
526
495
|
request: Request,
|
527
496
|
common: CommonQueryParams,
|
528
497
|
title: str,
|
529
|
-
conversation_id: Optional[
|
498
|
+
conversation_id: Optional[str] = None,
|
530
499
|
) -> Response:
|
531
500
|
user = request.user.object
|
532
501
|
title = title.strip()[:200]
|
@@ -556,7 +525,7 @@ class ChatRequestBody(BaseModel):
|
|
556
525
|
d: Optional[float] = None
|
557
526
|
stream: Optional[bool] = False
|
558
527
|
title: Optional[str] = None
|
559
|
-
conversation_id: Optional[
|
528
|
+
conversation_id: Optional[str] = None
|
560
529
|
city: Optional[str] = None
|
561
530
|
region: Optional[str] = None
|
562
531
|
country: Optional[str] = None
|
@@ -1045,7 +1014,7 @@ async def get_chat(
|
|
1045
1014
|
d: float = None,
|
1046
1015
|
stream: Optional[bool] = False,
|
1047
1016
|
title: Optional[str] = None,
|
1048
|
-
conversation_id: Optional[
|
1017
|
+
conversation_id: Optional[str] = None,
|
1049
1018
|
city: Optional[str] = None,
|
1050
1019
|
region: Optional[str] = None,
|
1051
1020
|
country: Optional[str] = None,
|
khoj/routers/helpers.py
CHANGED
@@ -21,7 +21,7 @@ from typing import (
|
|
21
21
|
Tuple,
|
22
22
|
Union,
|
23
23
|
)
|
24
|
-
from urllib.parse import parse_qs, urljoin, urlparse
|
24
|
+
from urllib.parse import parse_qs, quote, urljoin, urlparse
|
25
25
|
|
26
26
|
import cron_descriptor
|
27
27
|
import pytz
|
@@ -632,6 +632,7 @@ async def send_message_to_model_wrapper(
|
|
632
632
|
messages=truncated_messages,
|
633
633
|
loaded_model=loaded_model,
|
634
634
|
model=chat_model,
|
635
|
+
max_prompt_size=max_tokens,
|
635
636
|
streaming=False,
|
636
637
|
response_type=response_type,
|
637
638
|
)
|
@@ -721,6 +722,7 @@ def send_message_to_model_wrapper_sync(
|
|
721
722
|
system_message=system_message,
|
722
723
|
model_name=chat_model,
|
723
724
|
loaded_model=loaded_model,
|
725
|
+
max_prompt_size=max_tokens,
|
724
726
|
vision_enabled=vision_available,
|
725
727
|
model_type=conversation_config.model_type,
|
726
728
|
)
|
@@ -729,6 +731,7 @@ def send_message_to_model_wrapper_sync(
|
|
729
731
|
messages=truncated_messages,
|
730
732
|
loaded_model=loaded_model,
|
731
733
|
model=chat_model,
|
734
|
+
max_prompt_size=max_tokens,
|
732
735
|
streaming=False,
|
733
736
|
response_type=response_type,
|
734
737
|
)
|
@@ -739,6 +742,7 @@ def send_message_to_model_wrapper_sync(
|
|
739
742
|
user_message=message,
|
740
743
|
system_message=system_message,
|
741
744
|
model_name=chat_model,
|
745
|
+
max_prompt_size=max_tokens,
|
742
746
|
vision_enabled=vision_available,
|
743
747
|
model_type=conversation_config.model_type,
|
744
748
|
)
|
@@ -795,7 +799,7 @@ def generate_chat_response(
|
|
795
799
|
conversation_commands: List[ConversationCommand] = [ConversationCommand.Default],
|
796
800
|
user: KhojUser = None,
|
797
801
|
client_application: ClientApplication = None,
|
798
|
-
conversation_id:
|
802
|
+
conversation_id: str = None,
|
799
803
|
location_data: LocationData = None,
|
800
804
|
user_name: Optional[str] = None,
|
801
805
|
uploaded_image_url: Optional[str] = None,
|
@@ -1098,7 +1102,7 @@ def scheduled_chat(
|
|
1098
1102
|
user: KhojUser,
|
1099
1103
|
calling_url: URL,
|
1100
1104
|
job_id: str = None,
|
1101
|
-
conversation_id:
|
1105
|
+
conversation_id: str = None,
|
1102
1106
|
):
|
1103
1107
|
logger.info(f"Processing scheduled_chat: {query_to_run}")
|
1104
1108
|
if job_id:
|
@@ -1127,7 +1131,8 @@ def scheduled_chat(
|
|
1127
1131
|
|
1128
1132
|
# Replace the original conversation_id with the conversation_id
|
1129
1133
|
if conversation_id:
|
1130
|
-
|
1134
|
+
# encode the conversation_id to avoid any issues with special characters
|
1135
|
+
query_dict["conversation_id"] = [quote(conversation_id)]
|
1131
1136
|
|
1132
1137
|
# Restructure the original query_dict into a valid JSON payload for the chat API
|
1133
1138
|
json_payload = {key: values[0] for key, values in query_dict.items()}
|
@@ -1181,7 +1186,7 @@ def scheduled_chat(
|
|
1181
1186
|
|
1182
1187
|
|
1183
1188
|
async def create_automation(
|
1184
|
-
q: str, timezone: str, user: KhojUser, calling_url: URL, meta_log: dict = {}, conversation_id:
|
1189
|
+
q: str, timezone: str, user: KhojUser, calling_url: URL, meta_log: dict = {}, conversation_id: str = None
|
1185
1190
|
):
|
1186
1191
|
crontime, query_to_run, subject = await schedule_query(q, meta_log)
|
1187
1192
|
job = await schedule_automation(query_to_run, subject, crontime, timezone, q, user, calling_url, conversation_id)
|
@@ -1196,7 +1201,7 @@ async def schedule_automation(
|
|
1196
1201
|
scheduling_request: str,
|
1197
1202
|
user: KhojUser,
|
1198
1203
|
calling_url: URL,
|
1199
|
-
conversation_id:
|
1204
|
+
conversation_id: str,
|
1200
1205
|
):
|
1201
1206
|
# Disable minute level automation recurrence
|
1202
1207
|
minute_value = crontime.split(" ")[0]
|
@@ -1214,7 +1219,7 @@ async def schedule_automation(
|
|
1214
1219
|
"scheduling_request": scheduling_request,
|
1215
1220
|
"subject": subject,
|
1216
1221
|
"crontime": crontime,
|
1217
|
-
"conversation_id": conversation_id,
|
1222
|
+
"conversation_id": str(conversation_id),
|
1218
1223
|
}
|
1219
1224
|
)
|
1220
1225
|
query_id = hashlib.md5(f"{query_to_run}_{crontime}".encode("utf-8")).hexdigest()
|
khoj/utils/cli.py
CHANGED
@@ -50,6 +50,12 @@ def cli(args=None):
|
|
50
50
|
default=False,
|
51
51
|
help="Run Khoj in anonymous mode. This does not require any login for connecting users.",
|
52
52
|
)
|
53
|
+
parser.add_argument(
|
54
|
+
"--non-interactive",
|
55
|
+
action="store_true",
|
56
|
+
default=False,
|
57
|
+
help="Start Khoj in non-interactive mode. Assumes interactive shell unavailable for config. E.g when run via Docker.",
|
58
|
+
)
|
53
59
|
|
54
60
|
args, remaining_args = parser.parse_known_args(args)
|
55
61
|
|
khoj/utils/constants.py
CHANGED
@@ -8,8 +8,15 @@ empty_escape_sequences = "\n|\r|\t| "
|
|
8
8
|
app_env_filepath = "~/.khoj/env"
|
9
9
|
telemetry_server = "https://khoj.beta.haletic.com/v1/telemetry"
|
10
10
|
content_directory = "~/.khoj/content/"
|
11
|
-
|
12
|
-
|
11
|
+
default_offline_chat_models = [
|
12
|
+
"bartowski/Meta-Llama-3.1-8B-Instruct-GGUF",
|
13
|
+
"bartowski/gemma-2-9b-it-GGUF",
|
14
|
+
"bartowski/gemma-2-2b-it-GGUF",
|
15
|
+
"bartowski/Phi-3.5-mini-instruct-GGUF",
|
16
|
+
]
|
17
|
+
default_openai_chat_models = ["gpt-4o-mini", "gpt-4o"]
|
18
|
+
default_gemini_chat_models = ["gemini-1.5-flash", "gemini-1.5-pro"]
|
19
|
+
default_anthropic_chat_models = ["claude-3-5-sonnet-20240620", "claude-3-opus-20240229"]
|
13
20
|
|
14
21
|
empty_config = {
|
15
22
|
"search-type": {
|