khoj 1.42.2.dev1__py3-none-any.whl → 1.42.2.dev16__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 +2 -0
- khoj/database/adapters/__init__.py +6 -6
- khoj/interface/compiled/404/index.html +2 -2
- khoj/interface/compiled/_next/static/chunks/{2327-f03b2a77f67b8f8c.js → 2327-aa22697ed9c8d54a.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/7127-79a3af5138960272.js +1 -0
- khoj/interface/compiled/_next/static/chunks/{5138-81457f7f59956b56.js → 7211-7fedd2ee3655239c.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/agents/layout-4e2a134ec26aa606.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/automations/page-ef89ac958e78aa81.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/chat/layout-ad4d1792ab1a4108.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/chat/page-db0fbea54ccea62f.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/share/chat/{page-9a167dc9b5fcd464.js → page-da90c78180a86040.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/{webpack-1c900156837baf90.js → webpack-0f15e6b51732b337.js} +1 -1
- khoj/interface/compiled/_next/static/css/{c34713c98384ee87.css → 2945c4a857922f3b.css} +1 -1
- khoj/interface/compiled/_next/static/css/{9c223d337a984468.css → 7017ee76c2f2cd87.css} +1 -1
- khoj/interface/compiled/_next/static/css/9a460202d29476e5.css +1 -0
- khoj/interface/compiled/agents/index.html +2 -2
- khoj/interface/compiled/agents/index.txt +2 -2
- khoj/interface/compiled/automations/index.html +2 -2
- khoj/interface/compiled/automations/index.txt +3 -3
- khoj/interface/compiled/chat/index.html +2 -2
- khoj/interface/compiled/chat/index.txt +2 -2
- khoj/interface/compiled/index.html +2 -2
- khoj/interface/compiled/index.txt +2 -2
- khoj/interface/compiled/search/index.html +2 -2
- khoj/interface/compiled/search/index.txt +2 -2
- khoj/interface/compiled/settings/index.html +2 -2
- khoj/interface/compiled/settings/index.txt +4 -4
- khoj/interface/compiled/share/chat/index.html +2 -2
- khoj/interface/compiled/share/chat/index.txt +2 -2
- khoj/processor/conversation/anthropic/anthropic_chat.py +17 -132
- khoj/processor/conversation/anthropic/utils.py +1 -1
- khoj/processor/conversation/google/gemini_chat.py +18 -139
- khoj/processor/conversation/offline/chat_model.py +21 -151
- khoj/processor/conversation/openai/gpt.py +12 -126
- khoj/processor/conversation/prompts.py +2 -63
- khoj/routers/api.py +5 -533
- khoj/routers/api_automation.py +243 -0
- khoj/routers/api_chat.py +35 -116
- khoj/routers/helpers.py +329 -80
- khoj/routers/research.py +3 -33
- khoj/utils/helpers.py +0 -6
- {khoj-1.42.2.dev1.dist-info → khoj-1.42.2.dev16.dist-info}/METADATA +1 -1
- {khoj-1.42.2.dev1.dist-info → khoj-1.42.2.dev16.dist-info}/RECORD +54 -53
- khoj/interface/compiled/_next/static/chunks/7127-d3199617463d45f0.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/agents/layout-e00fb81dca656a10.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/automations/page-465741d9149dfd48.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/chat/layout-33934fc2d6ae6838.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/chat/page-1726184cf1c1b86e.js +0 -1
- khoj/interface/compiled/_next/static/css/fca983d49c3dd1a3.css +0 -1
- /khoj/interface/compiled/_next/static/{Dzg_ViqMwQEjqMgetZPRc → OTsOjbrtuaYMukpuJS4sy}/_buildManifest.js +0 -0
- /khoj/interface/compiled/_next/static/{Dzg_ViqMwQEjqMgetZPRc → OTsOjbrtuaYMukpuJS4sy}/_ssgManifest.js +0 -0
- /khoj/interface/compiled/_next/static/chunks/{1915-ab4353eaca76f690.js → 1915-1943ee8a628b893c.js} +0 -0
- /khoj/interface/compiled/_next/static/chunks/{2117-1c18aa2098982bf9.js → 2117-5a41630a2bd2eae8.js} +0 -0
- /khoj/interface/compiled/_next/static/chunks/{4363-4efaf12abe696251.js → 4363-e6ac2203564d1a3b.js} +0 -0
- /khoj/interface/compiled/_next/static/chunks/{4447-5d44807c40355b1a.js → 4447-e038b251d626c340.js} +0 -0
- /khoj/interface/compiled/_next/static/chunks/{8667-adbe6017a66cef10.js → 8667-8136f74e9a086fca.js} +0 -0
- /khoj/interface/compiled/_next/static/chunks/{9259-d8bcd9da9e80c81e.js → 9259-640fdd77408475df.js} +0 -0
- {khoj-1.42.2.dev1.dist-info → khoj-1.42.2.dev16.dist-info}/WHEEL +0 -0
- {khoj-1.42.2.dev1.dist-info → khoj-1.42.2.dev16.dist-info}/entry_points.txt +0 -0
- {khoj-1.42.2.dev1.dist-info → khoj-1.42.2.dev16.dist-info}/licenses/LICENSE +0 -0
@@ -1,14 +1,11 @@
|
|
1
|
-
import asyncio
|
2
1
|
import logging
|
3
|
-
from datetime import datetime
|
2
|
+
from datetime import datetime
|
4
3
|
from typing import AsyncGenerator, Dict, List, Optional
|
5
4
|
|
6
|
-
import pyjson5
|
7
|
-
from langchain_core.messages.chat import ChatMessage
|
8
5
|
from openai.lib._pydantic import _ensure_strict_json_schema
|
9
6
|
from pydantic import BaseModel
|
10
7
|
|
11
|
-
from khoj.database.models import Agent, ChatMessageModel, ChatModel
|
8
|
+
from khoj.database.models import Agent, ChatMessageModel, ChatModel
|
12
9
|
from khoj.processor.conversation import prompts
|
13
10
|
from khoj.processor.conversation.openai.utils import (
|
14
11
|
chat_completion_with_backoff,
|
@@ -19,105 +16,16 @@ from khoj.processor.conversation.utils import (
|
|
19
16
|
JsonSupport,
|
20
17
|
OperatorRun,
|
21
18
|
ResponseWithThought,
|
22
|
-
clean_json,
|
23
|
-
construct_question_history,
|
24
|
-
construct_structured_message,
|
25
19
|
generate_chatml_messages_with_context,
|
26
20
|
messages_to_print,
|
27
21
|
)
|
28
|
-
from khoj.utils.helpers import
|
29
|
-
ConversationCommand,
|
30
|
-
is_none_or_empty,
|
31
|
-
truncate_code_context,
|
32
|
-
)
|
22
|
+
from khoj.utils.helpers import is_none_or_empty, truncate_code_context
|
33
23
|
from khoj.utils.rawconfig import FileAttachment, LocationData
|
34
24
|
from khoj.utils.yaml import yaml_dump
|
35
25
|
|
36
26
|
logger = logging.getLogger(__name__)
|
37
27
|
|
38
28
|
|
39
|
-
def extract_questions(
|
40
|
-
text,
|
41
|
-
model: Optional[str] = "gpt-4o-mini",
|
42
|
-
chat_history: list[ChatMessageModel] = [],
|
43
|
-
api_key=None,
|
44
|
-
api_base_url=None,
|
45
|
-
location_data: LocationData = None,
|
46
|
-
user: KhojUser = None,
|
47
|
-
query_images: Optional[list[str]] = None,
|
48
|
-
vision_enabled: bool = False,
|
49
|
-
personality_context: Optional[str] = None,
|
50
|
-
query_files: str = None,
|
51
|
-
tracer: dict = {},
|
52
|
-
):
|
53
|
-
"""
|
54
|
-
Infer search queries to retrieve relevant notes to answer user query
|
55
|
-
"""
|
56
|
-
location = f"{location_data}" if location_data else "Unknown"
|
57
|
-
username = prompts.user_name.format(name=user.get_full_name()) if user and user.get_full_name() else ""
|
58
|
-
|
59
|
-
# Extract Past User Message and Inferred Questions from Chat History
|
60
|
-
chat_history_str = construct_question_history(chat_history)
|
61
|
-
|
62
|
-
# Get dates relative to today for prompt creation
|
63
|
-
today = datetime.today()
|
64
|
-
current_new_year = today.replace(month=1, day=1)
|
65
|
-
last_new_year = current_new_year.replace(year=today.year - 1)
|
66
|
-
|
67
|
-
prompt = prompts.extract_questions.format(
|
68
|
-
current_date=today.strftime("%Y-%m-%d"),
|
69
|
-
day_of_week=today.strftime("%A"),
|
70
|
-
current_month=today.strftime("%Y-%m"),
|
71
|
-
last_new_year=last_new_year.strftime("%Y"),
|
72
|
-
last_new_year_date=last_new_year.strftime("%Y-%m-%d"),
|
73
|
-
current_new_year_date=current_new_year.strftime("%Y-%m-%d"),
|
74
|
-
bob_tom_age_difference={current_new_year.year - 1984 - 30},
|
75
|
-
bob_age={current_new_year.year - 1984},
|
76
|
-
chat_history=chat_history_str,
|
77
|
-
text=text,
|
78
|
-
yesterday_date=(today - timedelta(days=1)).strftime("%Y-%m-%d"),
|
79
|
-
location=location,
|
80
|
-
username=username,
|
81
|
-
personality_context=personality_context,
|
82
|
-
)
|
83
|
-
|
84
|
-
prompt = construct_structured_message(
|
85
|
-
message=prompt,
|
86
|
-
images=query_images,
|
87
|
-
model_type=ChatModel.ModelType.OPENAI,
|
88
|
-
vision_enabled=vision_enabled,
|
89
|
-
attached_file_context=query_files,
|
90
|
-
)
|
91
|
-
|
92
|
-
messages = []
|
93
|
-
messages.append(ChatMessage(content=prompt, role="user"))
|
94
|
-
|
95
|
-
response = send_message_to_model(
|
96
|
-
messages,
|
97
|
-
api_key,
|
98
|
-
model,
|
99
|
-
response_type="json_object",
|
100
|
-
api_base_url=api_base_url,
|
101
|
-
tracer=tracer,
|
102
|
-
)
|
103
|
-
|
104
|
-
# Extract, Clean Message from GPT's Response
|
105
|
-
try:
|
106
|
-
response = clean_json(response)
|
107
|
-
response = pyjson5.loads(response)
|
108
|
-
response = [q.strip() for q in response["queries"] if q.strip()]
|
109
|
-
if not isinstance(response, list) or not response:
|
110
|
-
logger.error(f"Invalid response for constructing subqueries: {response}")
|
111
|
-
return [text]
|
112
|
-
return response
|
113
|
-
except:
|
114
|
-
logger.warning(f"GPT returned invalid JSON. Falling back to using user message as search query.\n{response}")
|
115
|
-
questions = [text]
|
116
|
-
|
117
|
-
logger.debug(f"Extracted Questions by GPT: {questions}")
|
118
|
-
return questions
|
119
|
-
|
120
|
-
|
121
29
|
def send_message_to_model(
|
122
30
|
messages,
|
123
31
|
api_key,
|
@@ -161,32 +69,32 @@ def send_message_to_model(
|
|
161
69
|
|
162
70
|
|
163
71
|
async def converse_openai(
|
72
|
+
# Query
|
164
73
|
user_query: str,
|
74
|
+
# Context
|
165
75
|
references: list[dict],
|
166
76
|
online_results: Optional[Dict[str, Dict]] = None,
|
167
77
|
code_results: Optional[Dict[str, Dict]] = None,
|
168
78
|
operator_results: Optional[List[OperatorRun]] = None,
|
79
|
+
query_images: Optional[list[str]] = None,
|
80
|
+
query_files: str = None,
|
81
|
+
generated_files: List[FileAttachment] = None,
|
82
|
+
generated_asset_results: Dict[str, Dict] = {},
|
83
|
+
program_execution_context: List[str] = None,
|
84
|
+
location_data: LocationData = None,
|
169
85
|
chat_history: list[ChatMessageModel] = [],
|
170
86
|
model: str = "gpt-4o-mini",
|
171
87
|
api_key: Optional[str] = None,
|
172
88
|
api_base_url: Optional[str] = None,
|
173
89
|
temperature: float = 0.4,
|
174
|
-
completion_func=None,
|
175
|
-
conversation_commands=[ConversationCommand.Default],
|
176
90
|
max_prompt_size=None,
|
177
91
|
tokenizer_name=None,
|
178
|
-
location_data: LocationData = None,
|
179
92
|
user_name: str = None,
|
180
93
|
agent: Agent = None,
|
181
|
-
query_images: Optional[list[str]] = None,
|
182
94
|
vision_available: bool = False,
|
183
|
-
query_files: str = None,
|
184
|
-
generated_files: List[FileAttachment] = None,
|
185
|
-
generated_asset_results: Dict[str, Dict] = {},
|
186
|
-
program_execution_context: List[str] = None,
|
187
95
|
deepthought: Optional[bool] = False,
|
188
96
|
tracer: dict = {},
|
189
|
-
) -> AsyncGenerator[
|
97
|
+
) -> AsyncGenerator[ResponseWithThought, None]:
|
190
98
|
"""
|
191
99
|
Converse with user using OpenAI's ChatGPT
|
192
100
|
"""
|
@@ -214,20 +122,6 @@ async def converse_openai(
|
|
214
122
|
user_name_prompt = prompts.user_name.format(name=user_name)
|
215
123
|
system_prompt = f"{system_prompt}\n{user_name_prompt}"
|
216
124
|
|
217
|
-
# Get Conversation Primer appropriate to Conversation Type
|
218
|
-
if conversation_commands == [ConversationCommand.Notes] and is_none_or_empty(references):
|
219
|
-
response = prompts.no_notes_found.format()
|
220
|
-
if completion_func:
|
221
|
-
asyncio.create_task(completion_func(chat_response=response))
|
222
|
-
yield response
|
223
|
-
return
|
224
|
-
elif conversation_commands == [ConversationCommand.Online] and is_none_or_empty(online_results):
|
225
|
-
response = prompts.no_online_results_found.format()
|
226
|
-
if completion_func:
|
227
|
-
asyncio.create_task(completion_func(chat_response=response))
|
228
|
-
yield response
|
229
|
-
return
|
230
|
-
|
231
125
|
context_message = ""
|
232
126
|
if not is_none_or_empty(references):
|
233
127
|
context_message = f"{prompts.notes_conversation.format(references=yaml_dump(references))}\n\n"
|
@@ -267,7 +161,6 @@ async def converse_openai(
|
|
267
161
|
logger.debug(f"Conversation Context for GPT: {messages_to_print(messages)}")
|
268
162
|
|
269
163
|
# Get Response from GPT
|
270
|
-
full_response = ""
|
271
164
|
async for chunk in chat_completion_with_backoff(
|
272
165
|
messages=messages,
|
273
166
|
model_name=model,
|
@@ -275,17 +168,10 @@ async def converse_openai(
|
|
275
168
|
openai_api_key=api_key,
|
276
169
|
api_base_url=api_base_url,
|
277
170
|
deepthought=deepthought,
|
278
|
-
model_kwargs={"stop": ["Notes:\n["]},
|
279
171
|
tracer=tracer,
|
280
172
|
):
|
281
|
-
if chunk.response:
|
282
|
-
full_response += chunk.response
|
283
173
|
yield chunk
|
284
174
|
|
285
|
-
# Call completion_func once finish streaming and we have the full response
|
286
|
-
if completion_func:
|
287
|
-
asyncio.create_task(completion_func(chat_response=full_response))
|
288
|
-
|
289
175
|
|
290
176
|
def clean_response_schema(schema: BaseModel | dict) -> dict:
|
291
177
|
"""
|
@@ -549,68 +549,7 @@ Q: {query}
|
|
549
549
|
)
|
550
550
|
|
551
551
|
|
552
|
-
|
553
|
-
"""
|
554
|
-
You are Khoj, an extremely smart and helpful document search assistant with only the ability to retrieve information from the user's notes and documents.
|
555
|
-
Construct search queries to retrieve relevant information to answer the user's question.
|
556
|
-
- You will be provided example and actual past user questions(Q), search queries(Khoj) and answers(A) for context.
|
557
|
-
- Add as much context from the previous questions and answers as required into your search queries.
|
558
|
-
- Break your search down into multiple search queries from a diverse set of lenses to retrieve all related documents.
|
559
|
-
- Add date filters to your search queries from questions and answers when required to retrieve the relevant information.
|
560
|
-
- When asked a meta, vague or random questions, search for a variety of broad topics to answer the user's question.
|
561
|
-
{personality_context}
|
562
|
-
What searches will you perform to answer the user's question? Respond with search queries as list of strings in a JSON object.
|
563
|
-
Current Date: {day_of_week}, {current_date}
|
564
|
-
User's Location: {location}
|
565
|
-
{username}
|
566
|
-
|
567
|
-
Examples
|
568
|
-
---
|
569
|
-
Q: How was my trip to Cambodia?
|
570
|
-
Khoj: {{"queries": ["How was my trip to Cambodia?", "Angkor Wat temple visit", "Flight to Phnom Penh", "Expenses in Cambodia", "Stay in Cambodia"]}}
|
571
|
-
A: The trip was amazing. You went to the Angkor Wat temple and it was beautiful.
|
572
|
-
|
573
|
-
Q: Who did i visit that temple with?
|
574
|
-
Khoj: {{"queries": ["Who did I visit the Angkor Wat Temple in Cambodia with?"]}}
|
575
|
-
A: You visited the Angkor Wat Temple in Cambodia with Pablo, Namita and Xi.
|
576
|
-
|
577
|
-
Q: What national parks did I go to last year?
|
578
|
-
Khoj: {{"queries": ["National park I visited in {last_new_year} dt>='{last_new_year_date}' dt<'{current_new_year_date}'"]}}
|
579
|
-
A: You visited the Grand Canyon and Yellowstone National Park in {last_new_year}.
|
580
|
-
|
581
|
-
Q: How can you help me?
|
582
|
-
Khoj: {{"queries": ["Social relationships", "Physical and mental health", "Education and career", "Personal life goals and habits"]}}
|
583
|
-
A: I can help you live healthier and happier across work and personal life
|
584
|
-
|
585
|
-
Q: How many tennis balls fit in the back of a 2002 Honda Civic?
|
586
|
-
Khoj: {{"queries": ["What is the size of a tennis ball?", "What is the trunk size of a 2002 Honda Civic?"]}}
|
587
|
-
A: 1085 tennis balls will fit in the trunk of a Honda Civic
|
588
|
-
|
589
|
-
Q: Share some random, interesting experiences from this month
|
590
|
-
Khoj: {{"queries": ["Exciting travel adventures from {current_month}", "Fun social events dt>='{current_month}-01' dt<'{current_date}'", "Intense emotional experiences in {current_month}"]}}
|
591
|
-
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.
|
592
|
-
|
593
|
-
Q: Is Bob older than Tom?
|
594
|
-
Khoj: {{"queries": ["When was Bob born?", "What is Tom's age?"]}}
|
595
|
-
A: Yes, Bob is older than Tom. As Bob was born on 1984-01-01 and Tom is 30 years old.
|
596
|
-
|
597
|
-
Q: What is their age difference?
|
598
|
-
Khoj: {{"queries": ["What is Bob's age?", "What is Tom's age?"]}}
|
599
|
-
A: Bob is {bob_tom_age_difference} years older than Tom. As Bob is {bob_age} years old and Tom is 30 years old.
|
600
|
-
|
601
|
-
Q: Who all did I meet here yesterday?
|
602
|
-
Khoj: {{"queries": ["Met in {location} on {yesterday_date} dt>='{yesterday_date}' dt<'{current_date}'"]}}
|
603
|
-
A: Yesterday's note mentions your visit to your local beach with Ram and Shyam.
|
604
|
-
|
605
|
-
Actual
|
606
|
-
---
|
607
|
-
{chat_history}
|
608
|
-
Q: {text}
|
609
|
-
Khoj:
|
610
|
-
""".strip()
|
611
|
-
)
|
612
|
-
|
613
|
-
extract_questions_anthropic_system_prompt = PromptTemplate.from_template(
|
552
|
+
extract_questions_system_prompt = PromptTemplate.from_template(
|
614
553
|
"""
|
615
554
|
You are Khoj, an extremely smart and helpful document search assistant with only the ability to retrieve information from the user's notes.
|
616
555
|
Construct search queries to retrieve relevant information to answer the user's question.
|
@@ -651,7 +590,7 @@ A: You had a great time at the local beach with your friends, attended a music c
|
|
651
590
|
""".strip()
|
652
591
|
)
|
653
592
|
|
654
|
-
|
593
|
+
extract_questions_user_message = PromptTemplate.from_template(
|
655
594
|
"""
|
656
595
|
Here's our most recent chat history:
|
657
596
|
{chat_history}
|