khoj 1.20.3__py3-none-any.whl → 1.20.5.dev10__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/configure.py +1 -0
- khoj/database/adapters/__init__.py +30 -11
- khoj/database/migrations/0056_searchmodelconfig_cross_encoder_model_config.py +17 -0
- khoj/database/models/__init__.py +2 -0
- khoj/interface/compiled/404/index.html +1 -1
- khoj/interface/compiled/_next/static/chunks/9178-ef3257c08d8973c8.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/agents/{page-922694b75f1fb67b.js → page-1ac024e05374f91f.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/automations/page-176fd855ffabf08e.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/chat/{page-51ab7c4b766ff344.js → page-8f7915867c7e42ba.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/factchecker/{page-60be5e3295e2c0bc.js → page-a6d96a122a65feb5.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/{page-635b30b582201b05.js → page-59e25010247e3780.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/search/{page-dcd385f03255ef36.js → page-fde8c956cc33a187.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/settings/{page-e83f6fa32691ca64.js → page-ab10cb1c576956fc.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/share/chat/{page-699b364dc6fbf139.js → page-de1049b418d21444.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/{webpack-97d9516936918753.js → webpack-f162a207b26413cd.js} +1 -1
- khoj/interface/compiled/_next/static/css/17e284bae7dc4881.css +1 -0
- khoj/interface/compiled/_next/static/css/2602b0918043c1e5.css +1 -0
- khoj/interface/compiled/_next/static/css/592ca99f5122e75a.css +1 -0
- khoj/interface/compiled/_next/static/css/6bde1f2045622ef7.css +1 -0
- khoj/interface/compiled/_next/static/css/9d5b867ec04494a6.css +25 -0
- khoj/interface/compiled/agents/index.html +1 -1
- khoj/interface/compiled/agents/index.txt +3 -3
- khoj/interface/compiled/assets/icons/khoj_lantern_logomarktype_1200x630.png +0 -0
- khoj/interface/compiled/automations/index.html +1 -1
- khoj/interface/compiled/automations/index.txt +3 -3
- khoj/interface/compiled/chat/index.html +1 -1
- khoj/interface/compiled/chat/index.txt +3 -3
- khoj/interface/compiled/factchecker/index.html +1 -1
- khoj/interface/compiled/factchecker/index.txt +3 -3
- khoj/interface/compiled/index.html +1 -1
- khoj/interface/compiled/index.txt +3 -3
- khoj/interface/compiled/khoj.webmanifest +51 -0
- khoj/interface/compiled/search/index.html +1 -1
- khoj/interface/compiled/search/index.txt +3 -3
- khoj/interface/compiled/settings/index.html +1 -1
- khoj/interface/compiled/settings/index.txt +3 -3
- khoj/interface/compiled/share/chat/index.html +1 -1
- khoj/interface/compiled/share/chat/index.txt +3 -3
- khoj/interface/web/base_config.html +1 -1
- khoj/interface/web/login.html +2 -2
- khoj/processor/conversation/anthropic/anthropic_chat.py +6 -2
- khoj/processor/conversation/offline/chat_model.py +15 -3
- khoj/processor/conversation/openai/gpt.py +6 -3
- khoj/processor/conversation/openai/utils.py +3 -1
- khoj/processor/conversation/prompts.py +20 -0
- khoj/processor/embeddings.py +3 -1
- khoj/processor/tools/online_search.py +9 -3
- khoj/routers/api.py +21 -4
- khoj/routers/api_chat.py +3 -3
- khoj/routers/email.py +2 -1
- khoj/routers/helpers.py +31 -6
- khoj/search_filter/file_filter.py +5 -2
- {khoj-1.20.3.dist-info → khoj-1.20.5.dev10.dist-info}/METADATA +1 -1
- {khoj-1.20.3.dist-info → khoj-1.20.5.dev10.dist-info}/RECORD +70 -68
- khoj/interface/compiled/_next/static/chunks/9178-859894e0d9d67aa5.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/automations/page-46913728bcb8f4c6.js +0 -1
- khoj/interface/compiled/_next/static/css/1de368beed21dfba.css +0 -25
- khoj/interface/compiled/_next/static/css/2272c73fc7a3b571.css +0 -1
- khoj/interface/compiled/_next/static/css/553f9cdcc7a2bcd6.css +0 -1
- khoj/interface/compiled/_next/static/css/a3530ec58b0b660f.css +0 -1
- khoj/interface/compiled/_next/static/css/df6f4c34ec280d53.css +0 -1
- khoj/interface/web/khoj.webmanifest +0 -51
- /khoj/interface/compiled/_next/static/chunks/{8423-132ea64eac83fd43.js → 8423-898d821eaab634af.js} +0 -0
- /khoj/interface/compiled/_next/static/chunks/{9417-2e54c6fd056982d8.js → 9417-5d14ac74aaab2c66.js} +0 -0
- /khoj/interface/compiled/_next/static/{iCI2Ycgat9pFGG9HeJvvH → n2f7OOHpHHaOEKtsWrb_9}/_buildManifest.js +0 -0
- /khoj/interface/compiled/_next/static/{iCI2Ycgat9pFGG9HeJvvH → n2f7OOHpHHaOEKtsWrb_9}/_ssgManifest.js +0 -0
- /khoj/interface/compiled/{favicon.ico → assets/icons/khoj_lantern.ico} +0 -0
- /khoj/interface/{web/assets/icons/favicon-128x128.png → compiled/assets/icons/khoj_lantern_128x128.png} +0 -0
- /khoj/interface/{web/assets/icons/favicon-256x256.png → compiled/assets/icons/khoj_lantern_256x256.png} +0 -0
- /khoj/interface/{web → compiled}/assets/samples/desktop-browse-draw-sample.png +0 -0
- /khoj/interface/{web → compiled}/assets/samples/desktop-plain-chat-sample.png +0 -0
- /khoj/interface/{web → compiled}/assets/samples/desktop-remember-plan-sample.png +0 -0
- /khoj/interface/{web → compiled}/assets/samples/phone-browse-draw-sample.png +0 -0
- /khoj/interface/{web → compiled}/assets/samples/phone-plain-chat-sample.png +0 -0
- /khoj/interface/{web → compiled}/assets/samples/phone-remember-plan-sample.png +0 -0
- {khoj-1.20.3.dist-info → khoj-1.20.5.dev10.dist-info}/WHEEL +0 -0
- {khoj-1.20.3.dist-info → khoj-1.20.5.dev10.dist-info}/entry_points.txt +0 -0
- {khoj-1.20.3.dist-info → khoj-1.20.5.dev10.dist-info}/licenses/LICENSE +0 -0
|
@@ -208,10 +208,12 @@ Construct search queries to retrieve relevant information to answer the user's q
|
|
|
208
208
|
- Add as much context from the previous questions and answers as required into your search queries.
|
|
209
209
|
- Break messages into multiple search queries when required to retrieve the relevant information.
|
|
210
210
|
- Add date filters to your search queries from questions and answers when required to retrieve the relevant information.
|
|
211
|
+
- When asked a meta, vague or random questions, search for a variety of broad topics to answer the user's question.
|
|
211
212
|
- Share relevant search queries as a JSON list of strings. Do not say anything else.
|
|
212
213
|
|
|
213
214
|
Current Date: {day_of_week}, {current_date}
|
|
214
215
|
User's Location: {location}
|
|
216
|
+
{username}
|
|
215
217
|
|
|
216
218
|
Examples:
|
|
217
219
|
Q: How was my trip to Cambodia?
|
|
@@ -238,6 +240,9 @@ Khoj: ["What kind of plants do I have?", "What issues do my plants have?"]
|
|
|
238
240
|
Q: Who all did I meet here yesterday?
|
|
239
241
|
Khoj: ["Met in {location} on {yesterday_date} dt>='{yesterday_date}' dt<'{current_date}'"]
|
|
240
242
|
|
|
243
|
+
Q: Share some random, interesting experiences from this month
|
|
244
|
+
Khoj: ["Exciting travel adventures from {current_month}", "Fun social events dt>='{current_month}-01' dt<'{current_date}'", "Intense emotional experiences in {current_month}"]
|
|
245
|
+
|
|
241
246
|
Chat History:
|
|
242
247
|
{chat_history}
|
|
243
248
|
What searches will you perform to answer the following question, using the chat history as reference? Respond only with relevant search queries as a valid JSON list of strings.
|
|
@@ -254,10 +259,12 @@ Construct search queries to retrieve relevant information to answer the user's q
|
|
|
254
259
|
- Add as much context from the previous questions and answers as required into your search queries.
|
|
255
260
|
- Break messages into multiple search queries when required to retrieve the relevant information.
|
|
256
261
|
- Add date filters to your search queries from questions and answers when required to retrieve the relevant information.
|
|
262
|
+
- When asked a meta, vague or random questions, search for a variety of broad topics to answer the user's question.
|
|
257
263
|
|
|
258
264
|
What searches will you perform to answer the users question? Respond with search queries as list of strings in a JSON object.
|
|
259
265
|
Current Date: {day_of_week}, {current_date}
|
|
260
266
|
User's Location: {location}
|
|
267
|
+
{username}
|
|
261
268
|
|
|
262
269
|
Q: How was my trip to Cambodia?
|
|
263
270
|
Khoj: {{"queries": ["How was my trip to Cambodia?"]}}
|
|
@@ -279,6 +286,10 @@ Q: How many tennis balls fit in the back of a 2002 Honda Civic?
|
|
|
279
286
|
Khoj: {{"queries": ["What is the size of a tennis ball?", "What is the trunk size of a 2002 Honda Civic?"]}}
|
|
280
287
|
A: 1085 tennis balls will fit in the trunk of a Honda Civic
|
|
281
288
|
|
|
289
|
+
Q: Share some random, interesting experiences from this month
|
|
290
|
+
Khoj: {{"queries": ["Exciting travel adventures from {current_month}", "Fun social events dt>='{current_month}-01' dt<'{current_date}'", "Intense emotional experiences in {current_month}"]}}
|
|
291
|
+
A: You had a great time at the local beach with your friends, attended a music concert and had a deep conversation with your friend, Khalid.
|
|
292
|
+
|
|
282
293
|
Q: Is Bob older than Tom?
|
|
283
294
|
Khoj: {{"queries": ["When was Bob born?", "What is Tom's age?"]}}
|
|
284
295
|
A: Yes, Bob is older than Tom. As Bob was born on 1984-01-01 and Tom is 30 years old.
|
|
@@ -305,11 +316,13 @@ Construct search queries to retrieve relevant information to answer the user's q
|
|
|
305
316
|
- Add as much context from the previous questions and answers as required into your search queries.
|
|
306
317
|
- Break messages into multiple search queries when required to retrieve the relevant information.
|
|
307
318
|
- Add date filters to your search queries from questions and answers when required to retrieve the relevant information.
|
|
319
|
+
- When asked a meta, vague or random questions, search for a variety of broad topics to answer the user's question.
|
|
308
320
|
|
|
309
321
|
What searches will you perform to answer the users question? Respond with a JSON object with the key "queries" mapping to a list of searches you would perform on the user's knowledge base. Just return the queries and nothing else.
|
|
310
322
|
|
|
311
323
|
Current Date: {day_of_week}, {current_date}
|
|
312
324
|
User's Location: {location}
|
|
325
|
+
{username}
|
|
313
326
|
|
|
314
327
|
Here are some examples of how you can construct search queries to answer the user's question:
|
|
315
328
|
|
|
@@ -328,6 +341,11 @@ A: I can help you live healthier and happier across work and personal life
|
|
|
328
341
|
User: Who all did I meet here yesterday?
|
|
329
342
|
Assistant: {{"queries": ["Met in {location} on {yesterday_date} dt>='{yesterday_date}' dt<'{current_date}'"]}}
|
|
330
343
|
A: Yesterday's note mentions your visit to your local beach with Ram and Shyam.
|
|
344
|
+
|
|
345
|
+
User: Share some random, interesting experiences from this month
|
|
346
|
+
Assistant: {{"queries": ["Exciting travel adventures from {current_month}", "Fun social events dt>='{current_month}-01' dt<'{current_date}'", "Intense emotional experiences in {current_month}"]}}
|
|
347
|
+
A: You had a great time at the local beach with your friends, attended a music concert and had a deep conversation with your friend, Khalid.
|
|
348
|
+
|
|
331
349
|
""".strip()
|
|
332
350
|
)
|
|
333
351
|
|
|
@@ -525,6 +543,7 @@ Which webpages will you need to read to answer the user's question?
|
|
|
525
543
|
Provide web page links as a list of strings in a JSON object.
|
|
526
544
|
Current Date: {current_date}
|
|
527
545
|
User's Location: {location}
|
|
546
|
+
{username}
|
|
528
547
|
|
|
529
548
|
Here are some examples:
|
|
530
549
|
History:
|
|
@@ -571,6 +590,7 @@ What Google searches, if any, will you need to perform to answer the user's ques
|
|
|
571
590
|
Provide search queries as a list of strings in a JSON object. Do not wrap the json in a codeblock.
|
|
572
591
|
Current Date: {current_date}
|
|
573
592
|
User's Location: {location}
|
|
593
|
+
{username}
|
|
574
594
|
|
|
575
595
|
Here are some examples:
|
|
576
596
|
History:
|
khoj/processor/embeddings.py
CHANGED
|
@@ -95,11 +95,13 @@ class CrossEncoderModel:
|
|
|
95
95
|
model_name: str = "mixedbread-ai/mxbai-rerank-xsmall-v1",
|
|
96
96
|
cross_encoder_inference_endpoint: str = None,
|
|
97
97
|
cross_encoder_inference_endpoint_api_key: str = None,
|
|
98
|
+
model_kwargs: dict = {},
|
|
98
99
|
):
|
|
99
100
|
self.model_name = model_name
|
|
100
|
-
self.cross_encoder_model = CrossEncoder(model_name=self.model_name, device=get_device())
|
|
101
101
|
self.inference_endpoint = cross_encoder_inference_endpoint
|
|
102
102
|
self.api_key = cross_encoder_inference_endpoint_api_key
|
|
103
|
+
self.model_kwargs = merge_dicts(model_kwargs, {"device": get_device()})
|
|
104
|
+
self.cross_encoder_model = CrossEncoder(model_name=self.model_name, **self.model_kwargs)
|
|
103
105
|
|
|
104
106
|
def inference_server_enabled(self) -> bool:
|
|
105
107
|
return self.api_key is not None and self.inference_endpoint is not None
|
|
@@ -10,6 +10,7 @@ import aiohttp
|
|
|
10
10
|
from bs4 import BeautifulSoup
|
|
11
11
|
from markdownify import markdownify
|
|
12
12
|
|
|
13
|
+
from khoj.database.models import KhojUser
|
|
13
14
|
from khoj.routers.helpers import (
|
|
14
15
|
ChatEvent,
|
|
15
16
|
extract_relevant_info,
|
|
@@ -51,6 +52,7 @@ async def search_online(
|
|
|
51
52
|
query: str,
|
|
52
53
|
conversation_history: dict,
|
|
53
54
|
location: LocationData,
|
|
55
|
+
user: KhojUser,
|
|
54
56
|
send_status_func: Optional[Callable] = None,
|
|
55
57
|
custom_filters: List[str] = [],
|
|
56
58
|
):
|
|
@@ -61,7 +63,7 @@ async def search_online(
|
|
|
61
63
|
return
|
|
62
64
|
|
|
63
65
|
# Breakdown the query into subqueries to get the correct answer
|
|
64
|
-
subqueries = await generate_online_subqueries(query, conversation_history, location)
|
|
66
|
+
subqueries = await generate_online_subqueries(query, conversation_history, location, user)
|
|
65
67
|
response_dict = {}
|
|
66
68
|
|
|
67
69
|
if subqueries:
|
|
@@ -126,14 +128,18 @@ async def search_with_google(query: str) -> Tuple[str, Dict[str, List[Dict]]]:
|
|
|
126
128
|
|
|
127
129
|
|
|
128
130
|
async def read_webpages(
|
|
129
|
-
query: str,
|
|
131
|
+
query: str,
|
|
132
|
+
conversation_history: dict,
|
|
133
|
+
location: LocationData,
|
|
134
|
+
user: KhojUser,
|
|
135
|
+
send_status_func: Optional[Callable] = None,
|
|
130
136
|
):
|
|
131
137
|
"Infer web pages to read from the query and extract relevant information from them"
|
|
132
138
|
logger.info(f"Inferring web pages to read")
|
|
133
139
|
if send_status_func:
|
|
134
140
|
async for event in send_status_func(f"**Inferring web pages to read**"):
|
|
135
141
|
yield {ChatEvent.STATUS: event}
|
|
136
|
-
urls = await infer_webpage_urls(query, conversation_history, location)
|
|
142
|
+
urls = await infer_webpage_urls(query, conversation_history, location, user)
|
|
137
143
|
|
|
138
144
|
logger.info(f"Reading web pages at: {urls}")
|
|
139
145
|
if send_status_func:
|
khoj/routers/api.py
CHANGED
|
@@ -388,6 +388,7 @@ async def extract_references_and_questions(
|
|
|
388
388
|
conversation_log=meta_log,
|
|
389
389
|
should_extract_questions=True,
|
|
390
390
|
location_data=location_data,
|
|
391
|
+
user=user,
|
|
391
392
|
max_prompt_size=conversation_config.max_prompt_size,
|
|
392
393
|
)
|
|
393
394
|
elif conversation_config.model_type == ChatModelOptions.ModelType.OPENAI:
|
|
@@ -402,7 +403,7 @@ async def extract_references_and_questions(
|
|
|
402
403
|
api_base_url=base_url,
|
|
403
404
|
conversation_log=meta_log,
|
|
404
405
|
location_data=location_data,
|
|
405
|
-
|
|
406
|
+
user=user,
|
|
406
407
|
)
|
|
407
408
|
elif conversation_config.model_type == ChatModelOptions.ModelType.ANTHROPIC:
|
|
408
409
|
api_key = conversation_config.openai_config.api_key
|
|
@@ -413,6 +414,7 @@ async def extract_references_and_questions(
|
|
|
413
414
|
api_key=api_key,
|
|
414
415
|
conversation_log=meta_log,
|
|
415
416
|
location_data=location_data,
|
|
417
|
+
user=user,
|
|
416
418
|
)
|
|
417
419
|
|
|
418
420
|
# Collate search results as context for GPT
|
|
@@ -545,15 +547,19 @@ async def post_automation(
|
|
|
545
547
|
if not subject:
|
|
546
548
|
subject = await acreate_title_from_query(q)
|
|
547
549
|
|
|
550
|
+
title = f"Automation: {subject}"
|
|
551
|
+
|
|
548
552
|
# Create new Conversation Session associated with this new task
|
|
549
|
-
conversation = await ConversationAdapters.acreate_conversation_session(user, request.user.client_app)
|
|
553
|
+
conversation = await ConversationAdapters.acreate_conversation_session(user, request.user.client_app, title=title)
|
|
550
554
|
|
|
551
|
-
calling_url = request.url.replace(query=f"{request.url.query}
|
|
555
|
+
calling_url = request.url.replace(query=f"{request.url.query}")
|
|
552
556
|
|
|
553
557
|
# Schedule automation with query_to_run, timezone, subject directly provided by user
|
|
554
558
|
try:
|
|
555
559
|
# Use the query to run as the scheduling request if the scheduling request is unset
|
|
556
|
-
automation = await schedule_automation(
|
|
560
|
+
automation = await schedule_automation(
|
|
561
|
+
query_to_run, subject, crontime, timezone, q, user, calling_url, conversation.id
|
|
562
|
+
)
|
|
557
563
|
except Exception as e:
|
|
558
564
|
logger.error(f"Error creating automation {q} for {user.email}: {e}", exc_info=True)
|
|
559
565
|
return Response(
|
|
@@ -649,6 +655,16 @@ def edit_job(
|
|
|
649
655
|
automation_metadata["query_to_run"] = query_to_run
|
|
650
656
|
automation_metadata["subject"] = subject.strip()
|
|
651
657
|
automation_metadata["crontime"] = crontime
|
|
658
|
+
conversation_id = automation_metadata.get("conversation_id")
|
|
659
|
+
|
|
660
|
+
if not conversation_id:
|
|
661
|
+
title = f"Automation: {subject}"
|
|
662
|
+
|
|
663
|
+
# Create new Conversation Session associated with this new task
|
|
664
|
+
conversation = ConversationAdapters.create_conversation_session(user, request.user.client_app, title=title)
|
|
665
|
+
|
|
666
|
+
conversation_id = conversation.id
|
|
667
|
+
automation_metadata["conversation_id"] = conversation_id
|
|
652
668
|
|
|
653
669
|
# Modify automation with updated query, subject
|
|
654
670
|
automation.modify(
|
|
@@ -659,6 +675,7 @@ def edit_job(
|
|
|
659
675
|
"scheduling_request": q,
|
|
660
676
|
"user": user,
|
|
661
677
|
"calling_url": request.url,
|
|
678
|
+
"conversation_id": conversation_id,
|
|
662
679
|
},
|
|
663
680
|
)
|
|
664
681
|
|
khoj/routers/api_chat.py
CHANGED
|
@@ -146,7 +146,7 @@ async def sendfeedback(request: Request, data: FeedbackData):
|
|
|
146
146
|
|
|
147
147
|
|
|
148
148
|
@api_chat.post("/speech")
|
|
149
|
-
@requires(["authenticated"
|
|
149
|
+
@requires(["authenticated"])
|
|
150
150
|
async def text_to_speech(
|
|
151
151
|
request: Request,
|
|
152
152
|
common: CommonQueryParams,
|
|
@@ -792,7 +792,7 @@ async def chat(
|
|
|
792
792
|
if ConversationCommand.Online in conversation_commands:
|
|
793
793
|
try:
|
|
794
794
|
async for result in search_online(
|
|
795
|
-
defiltered_query, meta_log, location, partial(send_event, ChatEvent.STATUS), custom_filters
|
|
795
|
+
defiltered_query, meta_log, location, user, partial(send_event, ChatEvent.STATUS), custom_filters
|
|
796
796
|
):
|
|
797
797
|
if isinstance(result, dict) and ChatEvent.STATUS in result:
|
|
798
798
|
yield result[ChatEvent.STATUS]
|
|
@@ -809,7 +809,7 @@ async def chat(
|
|
|
809
809
|
if ConversationCommand.Webpage in conversation_commands:
|
|
810
810
|
try:
|
|
811
811
|
async for result in read_webpages(
|
|
812
|
-
defiltered_query, meta_log, location, partial(send_event, ChatEvent.STATUS)
|
|
812
|
+
defiltered_query, meta_log, location, user, partial(send_event, ChatEvent.STATUS)
|
|
813
813
|
):
|
|
814
814
|
if isinstance(result, dict) and ChatEvent.STATUS in result:
|
|
815
815
|
yield result[ChatEvent.STATUS]
|
khoj/routers/email.py
CHANGED
|
@@ -117,7 +117,8 @@ def send_task_email(name, email, query, result, subject, is_image=False):
|
|
|
117
117
|
template = env.get_template("task.html")
|
|
118
118
|
|
|
119
119
|
if is_image:
|
|
120
|
-
|
|
120
|
+
image = result.get("image")
|
|
121
|
+
result = f""
|
|
121
122
|
|
|
122
123
|
html_result = markdown_it.MarkdownIt().render(result)
|
|
123
124
|
html_content = template.render(name=name, subject=subject, query=query, result=html_result)
|
khoj/routers/helpers.py
CHANGED
|
@@ -340,11 +340,14 @@ async def aget_relevant_output_modes(query: str, conversation_history: dict, is_
|
|
|
340
340
|
return ConversationCommand.Text
|
|
341
341
|
|
|
342
342
|
|
|
343
|
-
async def infer_webpage_urls(
|
|
343
|
+
async def infer_webpage_urls(
|
|
344
|
+
q: str, conversation_history: dict, location_data: LocationData, user: KhojUser
|
|
345
|
+
) -> List[str]:
|
|
344
346
|
"""
|
|
345
347
|
Infer webpage links from the given query
|
|
346
348
|
"""
|
|
347
349
|
location = f"{location_data.city}, {location_data.region}, {location_data.country}" if location_data else "Unknown"
|
|
350
|
+
username = prompts.user_name.format(name=user.get_full_name()) if user.get_full_name() else ""
|
|
348
351
|
chat_history = construct_chat_history(conversation_history)
|
|
349
352
|
|
|
350
353
|
utc_date = datetime.utcnow().strftime("%Y-%m-%d")
|
|
@@ -353,6 +356,7 @@ async def infer_webpage_urls(q: str, conversation_history: dict, location_data:
|
|
|
353
356
|
query=q,
|
|
354
357
|
chat_history=chat_history,
|
|
355
358
|
location=location,
|
|
359
|
+
username=username,
|
|
356
360
|
)
|
|
357
361
|
|
|
358
362
|
with timer("Chat actor: Infer webpage urls to read", logger):
|
|
@@ -370,11 +374,14 @@ async def infer_webpage_urls(q: str, conversation_history: dict, location_data:
|
|
|
370
374
|
raise ValueError(f"Invalid list of urls: {response}")
|
|
371
375
|
|
|
372
376
|
|
|
373
|
-
async def generate_online_subqueries(
|
|
377
|
+
async def generate_online_subqueries(
|
|
378
|
+
q: str, conversation_history: dict, location_data: LocationData, user: KhojUser
|
|
379
|
+
) -> List[str]:
|
|
374
380
|
"""
|
|
375
381
|
Generate subqueries from the given query
|
|
376
382
|
"""
|
|
377
383
|
location = f"{location_data.city}, {location_data.region}, {location_data.country}" if location_data else "Unknown"
|
|
384
|
+
username = prompts.user_name.format(name=user.get_full_name()) if user.get_full_name() else ""
|
|
378
385
|
chat_history = construct_chat_history(conversation_history)
|
|
379
386
|
|
|
380
387
|
utc_date = datetime.utcnow().strftime("%Y-%m-%d")
|
|
@@ -383,6 +390,7 @@ async def generate_online_subqueries(q: str, conversation_history: dict, locatio
|
|
|
383
390
|
query=q,
|
|
384
391
|
chat_history=chat_history,
|
|
385
392
|
location=location,
|
|
393
|
+
username=username,
|
|
386
394
|
)
|
|
387
395
|
|
|
388
396
|
with timer("Chat actor: Generate online search subqueries", logger):
|
|
@@ -1074,7 +1082,13 @@ def should_notify(original_query: str, executed_query: str, ai_response: str) ->
|
|
|
1074
1082
|
|
|
1075
1083
|
|
|
1076
1084
|
def scheduled_chat(
|
|
1077
|
-
query_to_run: str,
|
|
1085
|
+
query_to_run: str,
|
|
1086
|
+
scheduling_request: str,
|
|
1087
|
+
subject: str,
|
|
1088
|
+
user: KhojUser,
|
|
1089
|
+
calling_url: URL,
|
|
1090
|
+
job_id: str = None,
|
|
1091
|
+
conversation_id: int = None,
|
|
1078
1092
|
):
|
|
1079
1093
|
logger.info(f"Processing scheduled_chat: {query_to_run}")
|
|
1080
1094
|
if job_id:
|
|
@@ -1101,6 +1115,10 @@ def scheduled_chat(
|
|
|
1101
1115
|
# Replace the original scheduling query with the scheduled query
|
|
1102
1116
|
query_dict["q"] = [query_to_run]
|
|
1103
1117
|
|
|
1118
|
+
# Replace the original conversation_id with the conversation_id
|
|
1119
|
+
if conversation_id:
|
|
1120
|
+
query_dict["conversation_id"] = [conversation_id]
|
|
1121
|
+
|
|
1104
1122
|
# Construct the URL to call the chat API with the scheduled query string
|
|
1105
1123
|
encoded_query = urlencode(query_dict, doseq=True)
|
|
1106
1124
|
url = f"{scheme}://{calling_url.netloc}/api/chat?{encoded_query}"
|
|
@@ -1130,7 +1148,9 @@ def scheduled_chat(
|
|
|
1130
1148
|
if raw_response.headers.get("Content-Type") == "application/json":
|
|
1131
1149
|
response_map = raw_response.json()
|
|
1132
1150
|
ai_response = response_map.get("response") or response_map.get("image")
|
|
1133
|
-
is_image =
|
|
1151
|
+
is_image = False
|
|
1152
|
+
if type(ai_response) == dict:
|
|
1153
|
+
is_image = ai_response.get("image") is not None
|
|
1134
1154
|
else:
|
|
1135
1155
|
ai_response = raw_response.text
|
|
1136
1156
|
|
|
@@ -1142,9 +1162,11 @@ def scheduled_chat(
|
|
|
1142
1162
|
return raw_response
|
|
1143
1163
|
|
|
1144
1164
|
|
|
1145
|
-
async def create_automation(
|
|
1165
|
+
async def create_automation(
|
|
1166
|
+
q: str, timezone: str, user: KhojUser, calling_url: URL, meta_log: dict = {}, conversation_id: int = None
|
|
1167
|
+
):
|
|
1146
1168
|
crontime, query_to_run, subject = await schedule_query(q, meta_log)
|
|
1147
|
-
job = await schedule_automation(query_to_run, subject, crontime, timezone, q, user, calling_url)
|
|
1169
|
+
job = await schedule_automation(query_to_run, subject, crontime, timezone, q, user, calling_url, conversation_id)
|
|
1148
1170
|
return job, crontime, query_to_run, subject
|
|
1149
1171
|
|
|
1150
1172
|
|
|
@@ -1156,6 +1178,7 @@ async def schedule_automation(
|
|
|
1156
1178
|
scheduling_request: str,
|
|
1157
1179
|
user: KhojUser,
|
|
1158
1180
|
calling_url: URL,
|
|
1181
|
+
conversation_id: int,
|
|
1159
1182
|
):
|
|
1160
1183
|
# Disable minute level automation recurrence
|
|
1161
1184
|
minute_value = crontime.split(" ")[0]
|
|
@@ -1173,6 +1196,7 @@ async def schedule_automation(
|
|
|
1173
1196
|
"scheduling_request": scheduling_request,
|
|
1174
1197
|
"subject": subject,
|
|
1175
1198
|
"crontime": crontime,
|
|
1199
|
+
"conversation_id": conversation_id,
|
|
1176
1200
|
}
|
|
1177
1201
|
)
|
|
1178
1202
|
query_id = hashlib.md5(f"{query_to_run}_{crontime}".encode("utf-8")).hexdigest()
|
|
@@ -1191,6 +1215,7 @@ async def schedule_automation(
|
|
|
1191
1215
|
"user": user,
|
|
1192
1216
|
"calling_url": calling_url,
|
|
1193
1217
|
"job_id": job_id,
|
|
1218
|
+
"conversation_id": conversation_id,
|
|
1194
1219
|
},
|
|
1195
1220
|
id=job_id,
|
|
1196
1221
|
name=job_metadata,
|
|
@@ -11,7 +11,8 @@ logger = logging.getLogger(__name__)
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class FileFilter(BaseFilter):
|
|
14
|
-
file_filter_regex = r'file:"(.+?)" ?'
|
|
14
|
+
file_filter_regex = r'(?<!-)file:"(.+?)" ?'
|
|
15
|
+
excluded_file_filter_regex = r'-file:"(.+?)" ?'
|
|
15
16
|
|
|
16
17
|
def __init__(self, entry_key="file"):
|
|
17
18
|
self.entry_key = entry_key
|
|
@@ -20,7 +21,9 @@ class FileFilter(BaseFilter):
|
|
|
20
21
|
|
|
21
22
|
def get_filter_terms(self, query: str) -> List[str]:
|
|
22
23
|
"Get all filter terms in query"
|
|
23
|
-
|
|
24
|
+
required_files = [f"{required_file}" for required_file in re.findall(self.file_filter_regex, query)]
|
|
25
|
+
excluded_files = [f"-{excluded_file}" for excluded_file in re.findall(self.excluded_file_filter_regex, query)]
|
|
26
|
+
return required_files + excluded_files
|
|
24
27
|
|
|
25
28
|
def convert_to_regex(self, file_filter: str) -> str:
|
|
26
29
|
"Convert file filter to regex"
|