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.
Files changed (60) hide show
  1. khoj/configure.py +2 -0
  2. khoj/database/adapters/__init__.py +6 -6
  3. khoj/interface/compiled/404/index.html +2 -2
  4. khoj/interface/compiled/_next/static/chunks/{2327-f03b2a77f67b8f8c.js → 2327-aa22697ed9c8d54a.js} +1 -1
  5. khoj/interface/compiled/_next/static/chunks/7127-79a3af5138960272.js +1 -0
  6. khoj/interface/compiled/_next/static/chunks/{5138-81457f7f59956b56.js → 7211-7fedd2ee3655239c.js} +1 -1
  7. khoj/interface/compiled/_next/static/chunks/app/agents/layout-4e2a134ec26aa606.js +1 -0
  8. khoj/interface/compiled/_next/static/chunks/app/automations/page-ef89ac958e78aa81.js +1 -0
  9. khoj/interface/compiled/_next/static/chunks/app/chat/layout-ad4d1792ab1a4108.js +1 -0
  10. khoj/interface/compiled/_next/static/chunks/app/chat/page-db0fbea54ccea62f.js +1 -0
  11. khoj/interface/compiled/_next/static/chunks/app/share/chat/{page-9a167dc9b5fcd464.js → page-da90c78180a86040.js} +1 -1
  12. khoj/interface/compiled/_next/static/chunks/{webpack-1c900156837baf90.js → webpack-0f15e6b51732b337.js} +1 -1
  13. khoj/interface/compiled/_next/static/css/{c34713c98384ee87.css → 2945c4a857922f3b.css} +1 -1
  14. khoj/interface/compiled/_next/static/css/{9c223d337a984468.css → 7017ee76c2f2cd87.css} +1 -1
  15. khoj/interface/compiled/_next/static/css/9a460202d29476e5.css +1 -0
  16. khoj/interface/compiled/agents/index.html +2 -2
  17. khoj/interface/compiled/agents/index.txt +2 -2
  18. khoj/interface/compiled/automations/index.html +2 -2
  19. khoj/interface/compiled/automations/index.txt +3 -3
  20. khoj/interface/compiled/chat/index.html +2 -2
  21. khoj/interface/compiled/chat/index.txt +2 -2
  22. khoj/interface/compiled/index.html +2 -2
  23. khoj/interface/compiled/index.txt +2 -2
  24. khoj/interface/compiled/search/index.html +2 -2
  25. khoj/interface/compiled/search/index.txt +2 -2
  26. khoj/interface/compiled/settings/index.html +2 -2
  27. khoj/interface/compiled/settings/index.txt +4 -4
  28. khoj/interface/compiled/share/chat/index.html +2 -2
  29. khoj/interface/compiled/share/chat/index.txt +2 -2
  30. khoj/processor/conversation/anthropic/anthropic_chat.py +17 -132
  31. khoj/processor/conversation/anthropic/utils.py +1 -1
  32. khoj/processor/conversation/google/gemini_chat.py +18 -139
  33. khoj/processor/conversation/offline/chat_model.py +21 -151
  34. khoj/processor/conversation/openai/gpt.py +12 -126
  35. khoj/processor/conversation/prompts.py +2 -63
  36. khoj/routers/api.py +5 -533
  37. khoj/routers/api_automation.py +243 -0
  38. khoj/routers/api_chat.py +35 -116
  39. khoj/routers/helpers.py +329 -80
  40. khoj/routers/research.py +3 -33
  41. khoj/utils/helpers.py +0 -6
  42. {khoj-1.42.2.dev1.dist-info → khoj-1.42.2.dev16.dist-info}/METADATA +1 -1
  43. {khoj-1.42.2.dev1.dist-info → khoj-1.42.2.dev16.dist-info}/RECORD +54 -53
  44. khoj/interface/compiled/_next/static/chunks/7127-d3199617463d45f0.js +0 -1
  45. khoj/interface/compiled/_next/static/chunks/app/agents/layout-e00fb81dca656a10.js +0 -1
  46. khoj/interface/compiled/_next/static/chunks/app/automations/page-465741d9149dfd48.js +0 -1
  47. khoj/interface/compiled/_next/static/chunks/app/chat/layout-33934fc2d6ae6838.js +0 -1
  48. khoj/interface/compiled/_next/static/chunks/app/chat/page-1726184cf1c1b86e.js +0 -1
  49. khoj/interface/compiled/_next/static/css/fca983d49c3dd1a3.css +0 -1
  50. /khoj/interface/compiled/_next/static/{Dzg_ViqMwQEjqMgetZPRc → OTsOjbrtuaYMukpuJS4sy}/_buildManifest.js +0 -0
  51. /khoj/interface/compiled/_next/static/{Dzg_ViqMwQEjqMgetZPRc → OTsOjbrtuaYMukpuJS4sy}/_ssgManifest.js +0 -0
  52. /khoj/interface/compiled/_next/static/chunks/{1915-ab4353eaca76f690.js → 1915-1943ee8a628b893c.js} +0 -0
  53. /khoj/interface/compiled/_next/static/chunks/{2117-1c18aa2098982bf9.js → 2117-5a41630a2bd2eae8.js} +0 -0
  54. /khoj/interface/compiled/_next/static/chunks/{4363-4efaf12abe696251.js → 4363-e6ac2203564d1a3b.js} +0 -0
  55. /khoj/interface/compiled/_next/static/chunks/{4447-5d44807c40355b1a.js → 4447-e038b251d626c340.js} +0 -0
  56. /khoj/interface/compiled/_next/static/chunks/{8667-adbe6017a66cef10.js → 8667-8136f74e9a086fca.js} +0 -0
  57. /khoj/interface/compiled/_next/static/chunks/{9259-d8bcd9da9e80c81e.js → 9259-640fdd77408475df.js} +0 -0
  58. {khoj-1.42.2.dev1.dist-info → khoj-1.42.2.dev16.dist-info}/WHEEL +0 -0
  59. {khoj-1.42.2.dev1.dist-info → khoj-1.42.2.dev16.dist-info}/entry_points.txt +0 -0
  60. {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, timedelta
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, KhojUser
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[str | ResponseWithThought, None]:
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
- extract_questions = PromptTemplate.from_template(
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
- extract_questions_anthropic_user_message = PromptTemplate.from_template(
593
+ extract_questions_user_message = PromptTemplate.from_template(
655
594
  """
656
595
  Here's our most recent chat history:
657
596
  {chat_history}